我的问题是类型如何与智能感知一起显示,我需要智能感知优先考虑别名类型而不是字符串的联合。
在这个例子中,el
的类型应该是T
的,但它给出了"a" | "b"
//this does not work:
const o = {a:"a", b:"b"};
type T = keyof typeof o;
const v: T[] = ["a"];
const el = v[0];
//this works:
type T2 = "a" | "b";
const v2: T2[] = ["a"];
const el2 = v2[0];
有什么办法可以解决这个问题吗?谢谢。
T
和"a" | "b"
的类型是等效的,基本上由编译器自行决定在 IntelliSense 中显示哪种形式。 它可以选择T
,或"a" | "b"
,或keyof typeof o
,或"b" | "a" | "a" | "b" | "a" | "a"
或Exclude<"c" | "r" | "a" | "b", "c" | "r">
或其他任何东西,只要它是等价的。编译器使用启发式方法做出决策,不完全预测哪些形式最有可能是开发人员希望看到的。这些预测是不完美的,因为编译器不如它试图取悦的开发人员那么聪明,也因为不同的开发人员会不同意哪种形式是可取的。 有人可能会出现,并且更喜欢在您的代码示例中"a" | "b"
T
。
无论如何,每隔一段时间,智能感知类型的显示启发式方法就会被调整,试图让人们更快乐。例如,请参阅 TypeScript 4.2 中为"更智能"类型别名保留添加的支持,以及它在 microsoft/TypeScript#42149 和 microsoft/TypeScript#42284 中的实现。
看起来当您以联合或交集的形式添加一些间接寻址时,启发式方法倾向于使用别名,而不是完全扩展类型定义。 找到一个不会改变类型但也不会立即简化为原始表示的并集或交集有点棘手,你不能写keyof typeof o | never
或keyof typeof o & never
,因为它们被积极地简化为keyof typeof o
显示为"a" | "b"
而不是T
。
目前似乎有效的一种方法(从 TS4.8 开始)是与空对象类型(也会减少,但不是立即减少)相交{}
:
const o = {a:"a", b:"b"};
type T = (keyof typeof o & {});
const v: T[] = ["a"];
const el = v[0];
// const el: T // <-- displays as T and not "a" | "b"
我不能保证这将始终有效,因为同样,这取决于编译器的自由裁量权以及该语言未来版本中可能更改的启发式方法。 (这个警告应用了很多TypeScript代码,因为整个语言的变化确实相当快。
但现在它的行为可以随心所欲。
操场链接到代码