比如说,我有一个自定义类型
export type Fruit = "apple" | "banana" | "grape";
我想确定字符串是否是水果类型的一部分.我怎样才能做到这一点?
下面的方法行不通.
let myfruit = "pear";
if (typeof myfruit === "Fruit") {
console.log("My fruit is of type 'Fruit'");
}
任何 idea 都很感激!
比如说,我有一个自定义类型
export type Fruit = "apple" | "banana" | "grape";
我想确定字符串是否是水果类型的一部分.我怎样才能做到这一点?
下面的方法行不通.
let myfruit = "pear";
if (typeof myfruit === "Fruit") {
console.log("My fruit is of type 'Fruit'");
}
任何 idea 都很感激!
简短回答:
不能在运行时使用typeof
判断interface
种类型,它们只在编译时存在.相反,你可以写一个user-defined type guard function来判断这些类型:
const fruit = ["apple", "banana", "grape"] as const;
type Fruit = (typeof fruit)[number];
const isFruit = (x: any): x is Fruit => fruit.includes(x);
let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}
答案如下:
您可能会对TypeScript中的值和类型之间的差异感到困惑,尤其是当它与typeof
运算符有关时.正如您可能知道的,TypeScript向JavaScript添加了一个静态类型系统,并添加了that type system gets erased when the code is transpiled.TypeScript的语法是这样的:一些表达式和语句引用运行时存在的values,而其他表达式和语句引用仅在设计/编译时存在的types.值不是类型,但它们本身不是类型.重要的是,在代码中的某些地方,编译器会期望得到一个值,并在可能的情况下将其找到的表达式解释为一个值;在其他地方,编译器会期望得到一个类型,并在可能的情况下将其找到的表达式解释为一个类型.
typeof
号操作员过着双重生活.表达式typeof x
总是希望x
是一个值,但typeof x
本身可能是一个值或类型,具体取决于上下文:
let bar = {a: 0};
let TypeofBar = typeof bar; // the value "object"
type TypeofBar = typeof bar; // the type {a: number}
第let TypeofBar = typeof bar;
行将进入JavaScript,它将在运行时使用JavaScript typeof operator并生成一个字符串.但是type TypeofBar = typeof bar
;它使用TypeScript type query operator判断TypeScript分配给名为bar
的值的静态类型.
在你的代码中,
let myfruit = "pear";
if (typeof myfruit === "Fruit") { // "string" === "Fruit" ?!
console.log("My fruit is of type 'Fruit'");
}
typeof myfruit
是一个值,而不是一种类型.所以它是JavaScript typeof
操作符,而不是TypeScript类型的查询操作符.它将始终返回值"string"
;它永远不会是Fruit
或"Fruit"
.在运行时无法获得TypeScript类型查询运算符的结果,因为类型系统在运行时被擦除.你需要放弃typeof
接线员.
你要做的是对照三个已知的Fruit
字符串文本判断myfruit
的值...比如说:
let myfruit = "pear";
if (myfruit === "apple" || myfruit === "banana" || myfruit === "grape") {
console.log("My fruit is of type 'Fruit'");
}
很好,对吧?好吧,也许这看起来有很多多余的代码.这里有一个不那么多余的方法.首先,根据现有的文本值数组定义Fruit
类型...TypeScript可以从值推断类型,但不能从类型生成值.
const fruit = ["apple", "banana", "grape"] as const;
export type Fruit = (typeof fruit)[number];
您可以验证Fruit
是否与您手动定义的类型相同.然后,对于型式试验,可以使用如下user-defined type guard:
const isFruit = (x: any): x is Fruit => fruit.includes(x);
isFruit()
是一个函数,它判断是否在fruit
数组中找到了它的参数,如果是,则将其参数的类型缩小为Fruit
.让我们看看它的工作:
let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}
该类型保护还让编译器知道,在if
语句的"then"子句中,myfruit
是Fruit
.想象一下,如果一个函数只接受Fruit
,而一个值可能是Fruit
,也可能不是Fruit
:
declare function acceptFruit(f: Fruit): void;
const myfruit = Math.random() < 0.5 ? "pear" : "banana";
不能直接调用该函数:
acceptFruit(myfruit); // error, myfruit might be "pear"
但在判断后,你可以在"then"子句中调用它:
if (isFruit(myfruit)) {
acceptFruit(myfruit); // okay, myfruit is known to be "banana"
}
这大概就是为什么首先要判断自定义类型.这样你就可以做到了.
总结一下:你不能用typeof
.你可以和字符串进行比较.您可以进行一些类型推断和类型保护,以消除重复代码,并从编译器中获得控制流类型分析.