当接口Foo
具有条件类型作为返回类型时,如何实现?
interface Foo {
<A, B>(a: A, b: B): A extends B ? string : number
}
const foo: Foo = (a, b) => a === b ? 'str' : 123
编译器会产生此错误:
Type '"str" | 123' is not assignable to type 'A extends B ? string : number'.
Type '"str"' is not assignable to type 'A extends B ? string : number'.
我已经看到this个问题,但看不到如何将其转换为示例。另外,与解决方法相比,我想知道什么是正式/正确的方法。
UPD:我像提到的问题一样解决了问题,但是Unional的回答确实帮助我理解了问题。我是这样解决的:
interface Foo {
<A, B>(a: A, b: B): A extends B ? string : number
<A, B>(a: A, b: B): string | number
}
答案 0 :(得分:1)
您的类型定义很好。
问题在于您似乎过于依赖类型系统来指导开发。
由于您将类型定义和实现分开,因此编译器自然会以不同的方式看待它们。
在这种情况下,请随时将实现强制转换为any
。
您看到的错误是由于类型推断而为您的实现创建了类型(a: any, b: any) => "str" | 123
。
因此编译器抱怨该类型不能满足您在Foo
中定义的类型。
没有其他信息,这是编译器可以做的最好的事情。
当然,在实现代码时,编译器推断的类型最终可能会满足您定义的类型。
但是请记住,使用TypeScript的主要目的是提供信息以使用您编写的代码。使用类型来辅助实现是很好的做法,但应该将其视为奖励。
编译器并不完美,您是唯一真正了解您意图的编译器。
这就是为什么有时需要使用any
来进行操作的原因,请使用它(当然要始终保持谨慎)。
这表明您的类型有效:
interface B { x: string }
interface A extends B { }
let a: A
let b: B
let c: string
const y = foo(a, b) // y is string
const x = foo(c, b) // x is number
请记住编写单元测试以证明您的实现。 类型可以帮助您避免一类错误,但不是所有错误。
更新:从TypeScript 3.2开始,我认为控制流分析(类型推断)不能推断条件类型。