映射类型如何与基本类型一起使用?

时间:2020-07-13 18:07:44

标签: typescript

我不明白为什么在type T0以下情况下是字符串而不是键为“ toString”,“ slice”“ split”的对象,以及为什么type T1是对象键类型为string的密钥,而现在我们的任何键都是string | symbol | number

type MappedType<T> = {
[K in keyof T]: T;
}

type T0 = MappedType<string>;
type T1 = MappedType<any>;

1 个答案:

答案 0 :(得分:2)

可以在实现“同态pull request”的mapped typesT0形式的映射类型中找到{[K in keyof T]: ...}的权威答案,其中T是通用类型参数。 (请注意,它最初被称为“同构”而不是“同构”,但是是同一回事。)

这种映射类型的正常使用情况是T是某种objdct类型;在这种情况下,映射会保留T中的键名以及它们的“只读”和“可选性”修饰符。 (可以通过在映射类型中显式设置它们来覆盖这些修饰符。)

那么当T是像string这样的原始类型时会发生什么?拉取请求显示“我们只是产生该原始类型”。事实证明,这非常有用,尤其是在您递归使用映射类型的情况下。像

type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> }

将遍历嵌套的对象类型,并使每个子属性为可选... 并保留基元

declare const ab: DeepPartial<{ a: { b: string } }>;
const str = ab.a!.b!; // string

这几乎总是人们想要的。如果这种类型继续向下递归到诸如lengthtoUpperCase之类的已包装基元的所有属性中,则最终会产生大量无用的类型。然后,获得“正常”版本的唯一方法是使用conditional types终止下降而不是映射基元:

type DeepPartial2<T> = 
  { [K in keyof T]?: T[K] extends object ? DeepPartial2<T[K]> : T[K] }

这不太方便(并且直到TS2.8引入条件类型才可能)。

从某种意义上讲,人们通常希望为同构映射的事物保留“相同的总体形状”,但是“相同的总体形状”的含义并不总是很明显。对象类型保持对象类型。原始保持原始。最初,数组被视为常规对象类型,产生了几乎无用的类型,将数组方法转换为无法识别的类型。这对任何人来说都不令人满意,这就是为什么TypeScript 3.1 changed it使得映射的数组类型仍然是数组类型,而映射的元组类型仍然是元组类型。


这使我们有了T1,在any的属性上进行同态映射会产生可索引的类型。

先前链接的拉取请求没有加入,但是实现者在commentGitHub issue中解释了他的推理,并将此行为报告为错误:

keyof anystring | number | symbol,因此应用于any的映射类型将产生{ [x: string]: XXX }的等效值。

请注意,他说“等于”。 symbol会自动从映射类型中删除,因此{[K in "a" | symbol]: string}会产生{a: string}。您可以 分别拥有stringnumber索引,因此{[K in string | number]: string}{[k: string]: string; [k: number]: string}。但是由于数字键在TypeScriptJavaScript中被认为是字符串值,因此它与{[k: string]: string}相同。 (如果您想详细了解stringnumbersymbol键在映射时会发生什么,则可以看到this documentation。)

我个人并不是100%地将keyof any映射到一个string索引,而不是同时映射到stringnumber,因为{{1} }会有所不同...但这只是次要点。

重要的一点是评论的其余部分:

您可能会争辩说,在将同态映射类型应用于{[K in keyof T]: K}时,我们应该只产生any,但这不太精确。例如,以any实例化为{ [K in keyof T]: number }的{​​{1}}实际上应该产生T而不只是any

所以你去了; { [x: string]: number }被视为具有可索引字符串的键的对象类型,因此在其上进行映射会产生合理的结果。该评论是我所看到的最接近该问题的规范答案。


好的,希望能有所帮助;祝你好运!

Playground link to code