我有一个自定义类型,比方说
export type Fruit = "apple" | "banana" | "grape";
Run Code Online (Sandbox Code Playgroud)
我想确定一个字符串是否是Fruit类型的一部分.我怎么能做到这一点?
以下不起作用.
let myfruit = "pear";
if (typeof myfruit === "Fruit") {
console.log("My fruit is of type 'Fruit'");
}
Run Code Online (Sandbox Code Playgroud)
任何想法赞赏!
jca*_*alz 48
您可能会对TypeScript中值和类型之间的差异感到困惑,特别是因为它与typeof
运算符有关.您可能知道,TypeScript会向JavaScript添加静态类型系统,并且在编译代码时会删除该类型系统.TypeScript的语法是这样的,一些表达式和语句引用运行时存在的值,而其他表达式和语句引用仅在设计/编译时存在的类型.值具有类型,但它们本身不是类型.重要的是,在代码中有一些地方,编译器会期望一个值,并在可能的情况下将它找到的表达式解释为值,以及编译器期望类型的其他位置,并在可能的情况下将它找到的表达式解释为类型.
该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}
Run Code Online (Sandbox Code Playgroud)
该行将let TypeofBar = typeof bar;
通过JavaScript,它将在运行时使用JavaScript typeof运算符并生成一个字符串.但是type TypeofBar = typeof bar
; 被擦除,它使用TypeScript类型查询运算符来检查TypeScript已分配给名为的值的静态类型bar
.
在你的代码中,
let myfruit = "pear";
if (typeof myfruit === "Fruit") { // "string" === "Fruit" ?!
console.log("My fruit is of type 'Fruit'");
}
Run Code Online (Sandbox Code Playgroud)
typeof myfruit
是一个值,而不是一个类型.所以它是JavaScript typeof
运算符,而不是TypeScript类型查询运算符.它总会返回值"string"
; 它将永远不会Fruit
或"Fruit"
.您无法在运行时获取TypeScript类型查询运算符的结果,因为类型系统在运行时被擦除.你需要放弃typeof
运营商.
您可以做的是检查myfruit
三个已知Fruit
字符串文字的值...例如,这样:
let myfruit = "pear";
if (myfruit === "apple" || myfruit === "banana" || myfruit === "grape") {
console.log("My fruit is of type 'Fruit'");
}
Run Code Online (Sandbox Code Playgroud)
完美,对吗?好吧,也许这似乎是很多冗余的代码.这是一种不那么冗余的方法.首先,Fruit
根据现有的文字值数组定义您的类型... TypeScript可以从值推断类型,但不能从类型生成值.
const stringLitArray = <L extends string>(arr: L[]) => arr;
const fruit = stringLitArray(["apple", "banana", "grape"]);
export type Fruit = (typeof fruit)[number];
Run Code Online (Sandbox Code Playgroud)
您可以验证该Fruit
手动与您自己定义的类型相同.然后,对于类型测试,您可以使用这样的用户定义类型保护:
const isFruit = (x: any): x is Fruit => fruit.includes(x);
Run Code Online (Sandbox Code Playgroud)
isFruit()
是一个函数,它检查它的参数是否在fruit
数组中找到,如果是,则将其参数的类型缩小为Fruit
.让我们看看它是否有效:
let myfruit = "pear";
if (isFruit(myfruit)) {
console.log("My fruit is of type 'Fruit'");
}
Run Code Online (Sandbox Code Playgroud)
那个类型的守护程序也让编译器知道在if
语句的"then"子句中,myfruit
就是a Fruit
.想象一下,如果你有一个只接受的函数,Fruit
一个值可能是也可能不是Fruit
:
declare function acceptFruit(f: Fruit): void;
const myfruit = Math.random() < 0.5 ? "pear" : "banana";
Run Code Online (Sandbox Code Playgroud)
您不能直接调用该函数:
acceptFruit(myfruit); // error, myfruit might be "pear"
Run Code Online (Sandbox Code Playgroud)
但是你可以在检查之后在"then"子句中调用它:
if (isFruit(myfruit)) {
acceptFruit(myfruit); // okay, myfruit is known to be "banana"
}
Run Code Online (Sandbox Code Playgroud)
这可能是您想要首先检查自定义类型的原因.这样你就可以做到.
回顾一下:你无法使用typeof
.您可以与字符串进行比较.您可以执行一些类型推断和类型保护,以消除重复的代码并从编译器获取控制流类型分析.
希望有所帮助.祝好运.
typeof
在 TS 中:TS 中的运算typeof
符可以在 2 种不同的上下文中使用:
typeof
运算符,编译后将保留。表达式/值上下文
const hi = 'hi';
const one = 1;
const obj = {};
console.log(typeof hi, typeof 1, typeof obj);
// [LOG]: "string", "number", "object"
Run Code Online (Sandbox Code Playgroud)
输入上下文:
const obj1 = {foo: 1, bar: true};
const obj2 = {foo: 1, bar: ''};
// test has the type according to the structure of obj1
const test: typeof obj1 = {foo: 1, bar: true};
// typeof obj1 is the same as:
type sameAsTypeofObj1 = {foo: number, bar: string}
// test2 has the type according to the structure of obj1
const test2: typeof obj2 = {foo: 1, bar: true};
// In test2 we get a compile error since bar is not correct
// Since the type of obj2 is {foo: number, bar: string} we get the error:
// Type 'boolean' is not assignable to type 'string'
Run Code Online (Sandbox Code Playgroud)
对于您的具体问题,我认为您应该使用用户定义的类型防护。这是一个例子:
type Fruit = "apple" | "banana" | "grape";
let myfruit = "apple";
// user defined type guard
function isFruit(fruit: string): fruit is Fruit {
return ["apple", "banana", "grape"].indexOf(fruit) !== -1;
}
if (isFruit(myfruit)) {
// if this condition passes
// then TS compiler knows that myfruit is of the Fruit type
console.log(`${myfruit} is a Fruit.`}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
24816 次 |
最近记录: |