我有一个函数接受它的参数并返回一个可以处理这些参数的函数。不幸的是,我无法让TypeScript进行类型检查。以下是我的问题的简化示例:
type NoiseMaker<T extends Animal> = (animal: T) => void;
class Dog {
bark() {
console.log('Woof! Woof!');
}
}
class Cat {
meow() {
console.log('Meow')
}
}
type Animal = Dog | Cat;
const bark: NoiseMaker<Dog> = (dog: Dog) => {
dog.bark();
}
function getNoiseMaker<T extends Animal>(animal: T): NoiseMaker<T> {
if (animal instanceof Dog) {
// T is a Dog then, right?
return bark; // ERROR: Type '(dog: Dog) => void' is not assignable to type 'NoiseMaker<T>'.
// Type 'T' is not assignable to type 'Dog'
}
else {
throw new Error("I don't know that kind of animal");
}
}
getNoiseMaker()
返回一个适用于任何给定T
的函数。一旦TypeScript确定T
的类型是或扩展了Dog,为什么它不允许我返回bark
,这是NoiseMaker<Dog>
?
我在这里做错了什么?
答案 0 :(得分:1)
问题在于,Typescript不会根据方法中的代码分支来缩小泛型参数。 instanceof
类型保护实际上只会将animal
的类型从T
更改为T&Dog
,因此它会影响参数但不影响泛型类型。
最简单的解决方案是将通用签名保留为公共签名,但是您可以使用不同的实现签名来编写此代码(您将在函数内部松开某些类型的安全性,但公开它将完全相同)
function getNoiseMaker<T extends Animal>(animal: T): NoiseMaker<T>
function getNoiseMaker(animal: Animal): NoiseMaker<Animal> {
if (animal instanceof Dog) {
return bark; // Ok
}
else {
throw new Error("I don't know that kind of animal");
}
}
另一种选择是将bark
投射到any