TypeScript 条件类型的映射与受约束的泛型不同吗?

eva*_*nbb 8 typescript typescript-generics mapped-types

我无法理解为什么下面的代码会起作用:

type MapOverString<T extends string> = { [K in T]: K };

type IfStringMapOverIt<T> = T extends string ? MapOverString<T> : never;

type ThisWorks = MapOverString<'a'>;
// { a: 'a' }

type ThisAlsoWorks = IfStringMapOverIt<'a'>;
// { a: 'a' }

type Union = 'a' | 'b' | 'c';

type ThisWorksToo = MapOverString<Union>;
// { a: 'a', b: 'b', c: 'c' }

type ThisDoesnt = IfStringMapOverIt<Union>;
// MapOverString<'a'> | MapOverString<'b'> | MapOverString<'c'>
Run Code Online (Sandbox Code Playgroud)

游乐场链接

我必须失去了一些东西,因为MapOverStringIfStringMapOverIt看起来像他们应该相同的功能。

最终,我使用字符串文字和泛型来级联配置类型的排列。例如,如果您想StringConfig<T>配置 options 'a' | 'b' | 'c'

type ConfigMap<T> = T extends number
  ? NumberConfig
  : T extends string
    ? StringConfig<T>
    : never

type MyConfig = ConfigMap<'a' | 'b' | 'c'> // so many sad faces
Run Code Online (Sandbox Code Playgroud)

有人可以启发我吗?这里发生了什么?

Tit*_*mir 4

这是条件类型分布属性的一个应用。裸露类型参数的条件将触发此行为并T extends string满足此行为。您可能还会看到T extend TT extends anyT extends unknown出于这个原因而使用,只是为了触发分发。

您可以在手册中阅读有关分布式条件类型的更多信息

您可以通过对 tuple 使用条件来禁用分发[T] extends [string]。其效果类似于常规条件,只是因为类型参数不再显示裸分布。

type StringConfig<T extends string> = { [K in T]: K };
type NumberConfig ={}

type ConfigMap<T> = [T] extends [number]
  ? NumberConfig
  : [T] extends [string]
    ? StringConfig<T>
    : never

export type MyConfig = ConfigMap<'a' | 'b' | 'c'> // so many sad faces
let x:MyConfig = {
  a:'a',
  b:'b',
  c: 'c'
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接