我可以确定一个值是否与类型别名匹配吗?
Can I determine if a value matches a type alias?
在 TypeScript 中,我可以确定一个值 is/matches 是否是类型别名吗?
假设我有这种类型:
export type Name = "Jane" | "John";
然后在其他地方我想检查某个用户输入是否属于 Name
类型。 if (input instanceOf Name)
之类的东西不起作用。
这可能吗?
不,在运行时这些信息不存在,因此不能用于此类用例。
TypeScript 是结构类型语言。这意味着当你创建一个类型时,在左边你有一个名字,而在右边你有在运行时的精确类型表示。这里没有像在名义类型系统中那样的额外魔法(类 和枚举是例外)。
这意味着为了检查某些东西是否具有这种类型,我们需要进行显式检查或编写辅助函数来检查它。
function isName(a: unknown): a is Name {
return a === "Jane" || a === "John";
}
可能看起来比较繁琐,但一般来说如果做union类型的话,选项的数量应该是合理的。如果选项量真的很大,可能是数据模型不对,需要重新考虑是否需要这样的union。
您无法检查值是否与类型别名匹配。类型在运行时被擦除,因此任何运行时代码都不能依赖于它们。
如果您控制类型别名,我会建议创建一个数组来保存值,让 TS 为其推断类型,并从中派生联合。然后你可以检查一个值是否在数组中:
const Name = ["Jane", "John"] as const
export type Name = typeof Name[number];
function isName(a: unknown): a is Name {
return Name.indexOf(a as Name) != -1;
}
到目前为止,我所知道的唯一方法是从 const 数组生成类型别名,然后根据该数组检查您的名字。
const names = ["Jane", "John"] as const;
type Name = typeof names[number];
function isValidName(name: string): name is Name {
return names.includes(<Name> name);
}
用法:
const test: string = "John";
if (isValidName(test)) {
console.log(`${test} is a name`);
}
else {
console.log(`${test} is not a name`);
}
我仍然不明白为什么打字稿不能从类似
的东西编译
type Example = 'first' | 'second';
const exampleValues = [typeof Example] as const;
到
const exampleValues = ['first', 'second'];
答案 AFAIK 是“类型在运行时被擦除”,但是将类型别名编译为文字数组在运行时不需要类型信息。
- 它没有任何开销
- 保留 javascript
的运行时行为
- 并且不提供额外的运行时功能
这将允许开发人员在运行时通过在数组中查找值来验证字符串。
如果有办法做到这一点,请告诉我。
正如我所展示的,您可以执行相反的操作,从数组到类型别名,但是使用类型别名您可以过滤和组合类型,我有兴趣在编译时从类型别名转换为数组.
在 TypeScript 中,我可以确定一个值 is/matches 是否是类型别名吗?
假设我有这种类型:
export type Name = "Jane" | "John";
然后在其他地方我想检查某个用户输入是否属于 Name
类型。 if (input instanceOf Name)
之类的东西不起作用。
这可能吗?
不,在运行时这些信息不存在,因此不能用于此类用例。
TypeScript 是结构类型语言。这意味着当你创建一个类型时,在左边你有一个名字,而在右边你有在运行时的精确类型表示。这里没有像在名义类型系统中那样的额外魔法(类 和枚举是例外)。
这意味着为了检查某些东西是否具有这种类型,我们需要进行显式检查或编写辅助函数来检查它。
function isName(a: unknown): a is Name {
return a === "Jane" || a === "John";
}
可能看起来比较繁琐,但一般来说如果做union类型的话,选项的数量应该是合理的。如果选项量真的很大,可能是数据模型不对,需要重新考虑是否需要这样的union。
您无法检查值是否与类型别名匹配。类型在运行时被擦除,因此任何运行时代码都不能依赖于它们。
如果您控制类型别名,我会建议创建一个数组来保存值,让 TS 为其推断类型,并从中派生联合。然后你可以检查一个值是否在数组中:
const Name = ["Jane", "John"] as const
export type Name = typeof Name[number];
function isName(a: unknown): a is Name {
return Name.indexOf(a as Name) != -1;
}
到目前为止,我所知道的唯一方法是从 const 数组生成类型别名,然后根据该数组检查您的名字。
const names = ["Jane", "John"] as const;
type Name = typeof names[number];
function isValidName(name: string): name is Name {
return names.includes(<Name> name);
}
用法:
const test: string = "John";
if (isValidName(test)) {
console.log(`${test} is a name`);
}
else {
console.log(`${test} is not a name`);
}
我仍然不明白为什么打字稿不能从类似
的东西编译type Example = 'first' | 'second';
const exampleValues = [typeof Example] as const;
到
const exampleValues = ['first', 'second'];
答案 AFAIK 是“类型在运行时被擦除”,但是将类型别名编译为文字数组在运行时不需要类型信息。
- 它没有任何开销
- 保留 javascript 的运行时行为
- 并且不提供额外的运行时功能
这将允许开发人员在运行时通过在数组中查找值来验证字符串。
如果有办法做到这一点,请告诉我。 正如我所展示的,您可以执行相反的操作,从数组到类型别名,但是使用类型别名您可以过滤和组合类型,我有兴趣在编译时从类型别名转换为数组.