【发布时间】:2021-03-27 15:22:01
【问题描述】:
我翻阅了 TS 文档,但似乎无法找到关于以下内容为何非法的答案。
我可以用字符串定义一个联合类型,但是如果我使用对象属性的引用创建相同的联合类型,最终引用相同的字符串值,编译器就会不高兴。
Demo via typescript playground
// Success
export type SortOrderWithStrings = 'asc' | 'desc';
export const SortOrderStatic = {
ASC: 'asc',
DESC: 'desc',
}
// Fail
export type SortOrderWithObject = SortOrderStatic.ASC | SortOrderStatic.DESC;
错误如下。为什么这是命名空间问题?
Cannot find namespace 'SortOrderStatic'
Exported type alias 'SortOrderReference' has or is using private name 'SortOrderType'
最终,最好有一个Column 接口来定义支持的排序顺序类型,然后用SortOrderStatic 实例化一个Column 以避免魔术字符串,但根据上述情况,这并不似乎有可能。
interface Column {
label: string;
defaultSortOrder: SortOrderWithObject;
}
const MyColumn: Column = {
label: 'My Column',
defaultSortOrder: SortOrderStatic.ASC
}
如果我如下定义接口(使用SortOrderWithStrings),然后尝试使用SortOrderStatic,编译器再次不高兴。
interface Column {
label: string;
defaultSortOrder: SortOrderWithStrings;
}
const MyColumn: Column = {
label: 'My Column',
defaultSortOrder: SortOrderStatic.ASC
}
失败:
Type 'string' is not assignable to type 'SortOrderWithStrings'.
很明显我在这里遗漏了一些基本的东西,我很感激任何见解。
【问题讨论】:
-
“很明显我在这里遗漏了一些基本的东西”是的,你把 compile-time 和 runtime 混淆了。除非 编译时类型 是文字字符串,否则编译器无法保证对象属性的运行时访问是您认为的字符串。您的对象属性类型为
string,这意味着在运行时它可以是any 字符串。字符串字面量是不可变的(因此可以静态验证),对象属性访问量不大。 -
@JaredSmith 谢谢,好的,有道理。我想知道如果
SortOrderStatic的类型为interface { [x: string]: string; },编译器是否可以推断出预期的运行时类型。这还不够明确吗? -
在这种情况下我会使用an enum
-
@JaredSmith 谢谢,我认为您更新的评论对我有用。编译器无法知道我最终的
ASC会是什么。 -
没错。几乎每个人(包括我刚开始时的我!)对 TS 的所有问题都来自这种混淆。
标签: javascript typescript