这是我对打字稿的观察总结。
以下是一些代码:
type someTypeEnum = '1';
type someOtherTypeEnum = '2' | '3';
type combinedTypeEnum = someTypeEnum | someOtherTypeEnum;
这是第一种情况:-
function typeAssertion<T extends combinedTypeEnum>(args: T): args is someTypeEnum {
// The error i get
// A type predicate's type must be assignable to its parameter's type.
// Type '"1"' is not assignable to type 'T'.
return undefined;
}
我不明白为什么这件事失败了,因为如果我们这样做,我们已经将参数限制为CombinedEnum。
typeAssertion('4')
我们已经收到一条错误消息,指出'4'
不是有效的参数,所以为什么args is someTypeEnum
被认为是无效的谓词。
这是第二种情况:-
function typeAssertion(args: combinedTypeEnum): args is someTypeEnum {
return undefined;
}
这似乎很好,但是如果我们这样做:-
function someFunction<T extends combinedTypeEnum>(args: T): T {
if (typeAssertion(args)) {
// args here is 'T & "1"'
args
}
return args
};
为什么我们有T&“ 1”,而不仅仅是“ 1”,所以我们特别断言它是someTypeEnum。
我真的很好奇为什么做出这样的决定。 如果事情以不同的方式完成,看看事情会如何破裂真的很有帮助。
答案 0 :(得分:1)
extends
在具有字符串文字时没有多大意义。为了使说明更容易,让我使用其他类型。考虑以下三个类:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
当我们使用泛型时,实际类型由调用者设置:
function foo<T extends Animal>(arg: T) {}
foo(new Dog()); //T is Dog, equivalent to foo(arg: Dog) {}
foo(new Cat()); //T is Cat, equivalent to foo(arg: Cat) {}
现在您可能已经知道我们要去的地方。我们使用类型谓词:
function foo<T extends Animal>(arg: T): arg is Cat {}
当我们调用foo(new Dog())
时,最后一个示例与此等效:
function foo(arg: Dog): arg is Cat {}
当然这是行不通的或没有道理的。
对于第二个示例:变量的类型不变。关键是通过声明一个特定的类型,编译器允许您执行此类型可以完成的任何事情。