all articles

TypeScript generic 1

2019-06-25 @sunderls

typescript





组内决定开启noImplicitAny,有很多工作要做。项目启动时为了速度,这个flag设置为了false,改起来还很麻烦,因为大家开始的时候都不熟悉typescript,写的一些type也是最基本的interface之类的,并没有用到太高级的内容。直到这次关掉这个flag,才发觉很多高级的用法不学习是不行的。

所以今天看看有哪些高级的用法。

ref : https://www.typescriptlang.org/docs/handbook/generics.html

generic

我的个人理解就是动态type或者说模版。

比如这样一个function返回它接收到的参数,所以它的返回值的type取决于参数的type,是动态的


function identity(arg) {
    return arg;
}
const result = identity('string') // result被推断为 any

可以加上动态type, generic

function identity<T> (arg:T): T {
    return arg;
}

const result = identity('string') // result被推断为 string
const result2 = identity<'string'>('string') // 指明是string也可以
const result3 = identity<'string'>(123) // 报错,123不是string

当然T叫什么都可以,也可以是S。这个最基本的用法还算好理解。

generic function type

如何定一个fuction type给上面的function呢?首先可以这样

const identity2: <T>(arg: T) => T = identity // Function Type
const identity3: { <T>(arg: T): T } = identity // Object Type with Call signature

然后可以把type抽象出来

interface IdentityFunction {
    <T>(arg: T): T
}
const identity2: IdentityFunction = (arg) => arg

如果要指明是string,就把T当作参数一样传过去

interface IdentityFunction<T> {
    (arg: T): T
}
const identity2: IdentityFunction<string> = (arg) => arg

generic class type

同样的,class也可以接受一个T参数

class MyClass <T>{
     someMethod(arg: T): T  {
         return arg
     }

}

const instance = new MyClass<string>()
const result = instance.someMethod('string')

这样typescript就知道someMethod返回的result是string了

Generic Constraints

如果只是T的话在某些情况下还不够,比如如果我们要求T只能是string话,可以使用extends来限制

interface IdentityFunction<T extends string> {
    (arg: T): T
}
const identity2: IdentityFunction<number> = (arg) => arg // 报错,function模版只接受string

再比如我们如果需要要求两个param直接有某种关联,比如第一个参数必须是第二个参数object 的key

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

再强行要求第一个参数是string: string 的话

const getProperty = <T extends {[index: string]: string}, K extends keyof T>(obj: T, key: K): string => {
    return obj[key]
}

// 或者用record

const getProperty = <T extends Record<string, string>, K extends keyof T>(obj: T, key: K): string => {
    return obj[key]
}

class as generic param

如果T是一个class的话,为了让它能够new,需要用new(): T来指明它是个class

// 以下这种写法是不行的,因为A不知道可不可以new
const createInstance = <A>(c: A): A => {
    return new c()
}

// 这样写就可以了
const createInstance = <A>(c: new() => A): A => {
    return new c()
}

嗯,generic的基本就看完了。在看的同时,发现Record, Partial,Pickup, Omit,等Advanced Types 下次再聊。



如果觉得有帮助到你的话,
欢迎支付宝donate