TypeScript 映射类型:带嵌套的标记类型

vas*_*kch 4 typescript mapped-types

TypeScript 有没有办法创建高级类型文档中Flags提到的类型的嵌套版本?

这很有效:

type Flags<T> = {
  [P in keyof T]: boolean;
}

interface Colors {
  red: string;
  green: string;
  blue: string;
}

const activeColors: Flags<Colors> = {
  red: true,
  green: true,
  blue: false
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我想创建一个NestedFlags能够处理这样的嵌套对象的类型呢?

interface NestedColors {
  red: string;
  green: string;
  blue: string;
  more: {
    yellow: string;
    violet: string;
    black: string;
  }
}

const activeNestedColors: NestedFlags<NestedColors> {
  red: true,
  blue: false,
  green: true,
  more: {
    yellow: false,
    violet: true,
    black: true
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以NestedFlags用[P in keyof T]: boolean | NestedFlags<T[P]>. 该解决方案运行良好,除了它允许我创建一个对象,例如。more: false这在我的情况下是不可取的。

谢谢!

jca*_*alz 6

您可能希望在本月的某个时间(2018 年 3 月)发布映射条件类型,该类型将从 TypeScript v2.8 开始提供。您现在可以将它与typescript@next. 这是我如何实现它的第一个镜头:

type NestedFlags<T> = {
  [K in keyof T]: T[K] extends object ? NestedFlags<T[K]> : boolean
}
Run Code Online (Sandbox Code Playgroud)

上面的行使用条件类型三元类型语法。这意味着:对于 中的每个键T, for 的属性类型NestedFlags<T>将取决于原始属性是否为对象类型。如果原始属性不是对象类型,则对应的属性将为布尔值。如果原始属性是对象类型,则相应的属性将NestedFlags<>应用于该对象类型。

这为您提供了以下行为:

interface NestedColors {
  red: string;
  green: string;
  blue: string;
  more: {
    yellow: string;
    violet: string;
    black: string;
  }
}

// okay    
const activeNestedColors: NestedFlags<NestedColors> = {
  red: true,
  blue: false,
  green: true,
  more: {
    yellow: false,
    violet: true,
    black: true
  }
}

// error
const badActiveNestedColors: NestedFlags<NestedColors> = {
  red: true,
  blue: false,
  green: true,
  more: false
} 
// Types of property 'more' are incompatible.
// Type 'boolean' is not assignable to ...
Run Code Online (Sandbox Code Playgroud)

TypeScript 抱怨badActiveNestedColors,说不more应该是boolean.

希望有帮助。祝你好运!