函数
当我不知道返回值或者传入参数人的类型的时候,经常会使用any类型来定义函数:
function identity(arg: any): any {return arg;}
使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
function identity<T>(arg: T): T {return arg;}
使用
let output = identity<string>("myString"); // type of output will be 'string'
泛型类
泛型类看上去与泛型接口差不多。 泛型类使用(<>)括起泛型类型,跟在类名后面。
class GenericNumber<T> {zeroValue: T;add: (x: T, y: T) => T;}let myGenericNumber = new GenericNumber<number>();myGenericNumber.zeroValue = 0;myGenericNumber.add = function(x, y) { return x + y; };
GenericNumber类的使用是十分直观的,并且你可能已经注意到了,没有什么去限制它只能使用number类型。 也可以使用字符串或其它更复杂的类型。
let stringNumeric = new GenericNumber<string>();stringNumeric.zeroValue = "";stringNumeric.add = function(x, y) { return x + y; };console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
我们来看下 react的Componet是如何实现的:
class Component<P, S> {static contextType?: Context<any>;context: any;constructor(props: Readonly<P> | P);constructor(props: P, context: any);setState<K extends keyof S>(state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),callback?: () => void): void;forceUpdate(callback?: () => void): void;render(): ReactNode;refs: {[key: string]: ReactInstance};}
泛型约束
function loggingIdentity<T>(arg: T): T {console.log(arg.length); // Error: T doesn't have .lengthreturn arg;}
相比于操作any所有类型,我们想要限制函数去处理任意带有.length属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。
为此,我们定义一个接口来描述约束条件。 创建一个包含.length属性的接口,使用这个接口和extends关键字来实现约束.
interface Lengthwise {length: number;}function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length); // Now we know it has a .length property, so no more errorreturn arg;}
