当我尝试实现这样的事情时遇到
Type 'unknown' is not assignable to type 'number'
:
interface Foo<V = unknown> {
foo: (value: V) => void
}
class Bar implements Foo<number> {
foo(v: number) {}
}
function test(foo: Foo): void {}
test(new Bar) // complains:
// Argument of type 'Bar' is not assignable to parameter of type 'Foo<unknown>'.
// Types of property 'foo' are incompatible.
// Type '(v: number) => void' is not assignable to type '(value: unknown) => void'.
// Types of parameters 'v' and 'value' are incompatible.
// Type 'unknown' is not assignable to type 'number'.(2345)
为什么它会这样,考虑到
test
应该能够获得Foo
的不同实现,例如,我该如何重新设计它
class Bar2 implements Foo<string> {
foo(v: string) {}
}
输入断言:
test(new Bar as Foo) // it doesn't complain now, but imo it's dirty and bad DX workaround
尝试将
unknown
中的 Foo
替换为联合类型,例如string | number | ...
,但没有帮助。
实际上,这里的主要问题是
unknown
不能 被分配给除了它本身和 any
类型之外的任何东西。
如果你进一步简化你的示例
type FooFn = (value: unknown) => void
const testFooFn: FooFn = (n: number) => {} // Error
您会遇到与上面类似的错误。
Type '(n: number) => void' is not assignable to type 'FooFn'.
Types of parameters 'n' and 'value' are incompatible.
Type 'unknown' is not assignable to type 'number'.
正如评论中所建议的,一种选择是使用泛型来继承类型。
interface Foo<V = unknown> {
foo: (value: V) => void
}
class Bar implements Foo<number> {
foo(v: number) {
console.log(v)
}
}
function test<T>(foo: Foo<T>): void {}
test(new Bar()) // No Error
另一个选项是将
unknown
更改为 any
。请参阅此处的差异,但通常使用unknown
更好/更安全,但需要更多类型体操。
interface Foo<V = any> {
foo: (value: V) => void
}
class Bar implements Foo<number> {
foo(v: number) {
console.log(v)
}
}
function test(foo: Foo): void {}
test(new Bar()) // No Error