TypeScript泛型函数参数场景下如何处理多态返回类型
报错原因
你最初定义的HandlerFunction = <T extends Base>() => T是将泛型参数声明在函数层级,这个定义的语义是:该函数要支持调用方传入任意符合Base约束的T类型,并且返回对应T类型的实例。
比如调用方可以写出handler<BSub>()要求返回BSub实例,但你传入的getA固定返回ASub,完全不满足这个语义,因此TS抛出类型错误。
正确的类型定义方案
如果需要保留子类的完整类型提示,只要把泛型参数移到类型别名层级,同时给myFunc也加上泛型推导即可:
abstract class Base { } class ASub extends Base { a: string = ''; } class BSub extends Base { b: number = 0; } // 泛型声明在类型别名上,语义是:返回某一种Base子类的函数 type HandlerFunction<T extends Base = Base> = () => T; // myFunc也加上泛型,支持自动推导传入的handler返回的子类类型 const myFunc = <T extends Base>(handler:HandlerFunction<T>):void => { console.log('in myFunc, got handler: ', handler); // 此时handler的返回类型会自动跟随传入的参数推导,保留完整类型提示 const res = handler(); // 传getA时res自动识别为ASub,传getB时自动识别为BSub }; const getA = ():ASub => new ASub(); const getB = ():BSub => new BSub(); // 不再报错,且保留完整类型提示 myFunc(getA); myFunc(getB);
如果你不需要在myFunc内部感知具体子类类型,也可以直接简化HandlerFunction的定义为:
type HandlerFunction = () => Base;
这种写法也兼容所有返回Base子类的函数,只是myFunc内部拿到的返回值默认只会提示Base上的属性。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

