如何在TypeScript接口中定义泛型函数?遇类型不兼容错误求解
问题:接口中使用联合类型定义函数时出现类型不兼容错误
我找到一种用联合类型定义函数的方法:
type ValueType = number[] | string[] | number | string type X<T extends ValueType> = (inp: T) => void; const x: X<number> = (inp) => { inp // 类型为number }; const y: X<string> = (inp) => { inp // 类型为string };
但在接口中使用该逻辑时出现错误:
type ValueType = number[] | string[] | number | string interface I1<X>{ setValue: <X extends ValueType>(value: X) => void } const i1: I1<number> = { setValue: (value: number) => { console.log(value) } }
编译器提示信息:
TS2322: Type '(value: number) => void' is not assignable to type '<X extends ValueType>(value: X) => void'. Types of parameters 'value' and 'value' are incompatible. Type 'X' is not assignable to type 'number'. Type 'ValueType' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. test.ts(23, 3): The expected type comes from property 'setValue' which is declared here on type 'I1<number>'
我认为两段代码逻辑一致,请问问题出在哪里?
解答
核心问题在于接口里的setValue是泛型方法,而你定义的X<T>是泛型类型,二者逻辑完全不同:
- 泛型类型
X<T>:当你指定X<number>时,整个函数类型就被固定为(inp: number) => void,是一个接收number参数的具体函数类型。 - 接口
I1中的setValue:它是一个自身带泛型参数的方法,意味着这个方法需要能接收ValueType的任意子类型作为参数,而不是固定为某个具体类型。哪怕你给I1指定了泛型参数number,也不会影响setValue方法自身的泛型约束——因为方法的泛型参数X和接口的泛型参数X重名了,属于局部覆盖,完全是两个独立的参数。
要让接口实现和之前的逻辑一致,你需要把接口的泛型参数绑定到setValue的参数类型上,而不是给方法单独加泛型:
type ValueType = number[] | string[] | number | string interface I1<T extends ValueType>{ setValue: (value: T) => void } const i1: I1<number> = { setValue: (value: number) => { console.log(value) } }
这样修改后,I1<number>中的setValue就被固定为接收number参数的函数,和之前X<number>的逻辑完全匹配,不会再出现类型错误。
内容的提问来源于stack exchange,提问作者SageJustus
相关产品推荐
相关产品推荐

