本文案例来自type-challenges
该题是 lettCode 上面一道经典题目 题目链接
假设有一个叫 EffectModule
的类
class EffectModule {}
这个对象上的方法只可能有两种类型签名:
interface Action<T> {payload?: Ttype: string}asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>syncMethod<T, U>(action: Action<T>): Action<U>
这个对象上还可能有一些任意的非函数属性:
interface Action<T> {payload?: T;type: string;}class EffectModule {count = 1;message = 'hello!';delay(input: Promise<number>) {return input.then((i) => ({payload: `hello ${i}!`,type: 'delay',}));}setMessage(action: Action<Date>) {return {payload: action.payload!.getMilliseconds(),type: 'set-message',};}}
现在有一个叫 connect
的函数,它接受 EffectModule 实例,将它变成另一个对象,这个对象上只有EffectModule 的同名方法,但是方法的类型签名被改变了:
asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>> 变成了asyncMethod<T, U>(input: T): Action<U>
syncMethod<T, U>(action: Action<T>): Action<U> 变成了syncMethod<T, U>(action: T): Action<U>
例子:
EffectModule 定义如下:
interface Action<T> {payload?: T;type: string;}class EffectModule {count = 1;message = 'hello!';delay(input: Promise<number>) {return input.then((i) => ({payload: `hello ${i}!`,type: 'delay',}));}setMessage(action: Action<Date>) {return {payload: action.payload!.getMilliseconds(),type: 'set-message',};}}
connect 之后:
// 修改 Connect 的类型,让 connected 的类型变成预期的类型type Connect = (module: EffectModule) => any;const connect: Connect = (m) => ({delay: (input: number) => ({type: 'delay',payload: `hello 2`,}),setMessage: (input: Date) => ({type: 'set-message',payload: input.getMilliseconds(),}),});type Connected = {delay(input: number): Action<string>;setMessage(action: Date): Action<number>;};const effectModule = new EffectModule();const connected: Connected = connect(effectModule);
有一个 type Connect = (module: EffectModule) => any
,将 any
替换成题目的解答,让编译能够顺利通过