在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
介绍软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。 在像C#和Java这样的语言中,可以使用 泛型下面来创建第一个使用泛型的例子:identity 函数。 这个函数会返回任何传入它的值 不用泛型的话,这个函数可能是下面这样: function identity(arg: number): number { return arg; } 或者,我们使用 function identity(arg: any): any { return arg; } 使用 因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了类型变量,它是一种特殊的变量,只用于表示类型而不是值。 // <T> 称作泛型变量 function identity<T>(arg: T): T { return arg; } 我们给identity添加了类型变量 我们把这个版本的 我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数 let output = identity<string>("myString"); 这里我们明确的指定了 第二种方法更普遍。利用了类型推论 – 即编译器会根据传入的参数自动地帮助我们确定T的类型: let output = identity("myString"); 注意我们没必要使用尖括号( 使用泛型变量使用泛型创建像 看下之前 function identity<T>(arg: T): T { return arg; } 如果我们想同时打印出 function loggingIdentity<T>(arg: T): T { console.log(arg.length); // Error: T doesn't have .length return arg; } 如果这么做,编译器会报错说我们使用了 现在假设我们想操作 // 返回的是一个 T 类型的数组 function loggingIdentity<T>(arg: T[]): T[] { console.log(arg.length); return arg; } 你可以这样理解 泛型约束我们有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在 function loggingIdentity<T>(arg: T): T { console.log(arg.length); // Error: T doesn't have .length return arg; } 相比于操作any所有类型,我们想要限制函数去处理任意带有 为此,我们定义一个接口来描述约束条件。 创建一个包含 // 创建了一个接口,具有 number 类型 interface Lengthwise { length: number; } // 使用 extends 和接口 限制 T 的类型 function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; } 现在这个泛型函数被定义了约束,因此它不再是适用于任意类型: loggingIdentity(3); // 报错,number 是没有 length 属性的 我们需要传入符合约束类型的值,必须包含必须的属性:数组或者字符串都是有 length 属性的 loggingIdentity({length: 10, value: 3}); // 数组 loggingIdentity("abcd"); // 字符串 在泛型约束中使用类型参数你可以声明一个类型参数,且它被另一个类型参数所约束。 比如,现在我们想要用属性名从对象里获取这个属性。 并且我们想要确保这个属性存在于对象 // 使用 extends keyof 限制 K function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "a"); // x 里有 a 属性 getProperty(x, "m"); // 报错,x 里没有 m 属性。Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.
|
请发表评论