简体   繁体   English

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

[英]TypeScript mapped types: Flag type with nesting

Is there a way in TypeScript to create a nested version of a Flags type mentioned in Advanced types documentation? TypeScript中是否可以创建高级类型文档中提到的Flags类型的嵌套版本?

This works well: 这很好用:

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
}

But what if I wanted to create let's say a NestedFlags type that would be able to handle nested objects like this? 但是,如果我想创建一个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
  }
}

I am able to create a NestedFlags type with [P in keyof T]: boolean | NestedFlags<T[P]> 我可以使用[P in keyof T]: boolean | NestedFlags<T[P]>创建NestedFlags类型[P in keyof T]: boolean | NestedFlags<T[P]> [P in keyof T]: boolean | NestedFlags<T[P]> . [P in keyof T]: boolean | NestedFlags<T[P]> That solution works well except the fact that it allows me to create an object with eg. 该解决方案效果很好,除了它允许我使用例如创建对象。 more: false which is undesirable in my case. more: false ,这对我来说是不可取的。

Thank you! 谢谢!

You probably want mapped conditional types , which will be available starting in TypeScript v2.8, to be released sometime this month (March 2018). 您可能希望映射的条件类型 (将从TypeScript v2.8开始提供)在本月的某个时候(2018年3月)发布。 You can use it now with typescript@next . 您现在可以通过typescript@next使用它。 Here's a first shot at how I'd implement it: 这是我如何实现的第一枪:

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

The above line uses the conditional types ternary type syntax. 上一行使用条件类型三元类型语法。 It means: for every key in T , the property type for NestedFlags<T> will depend on whether the original property is an object type or not. 这意味着:对于T每个键, NestedFlags<T>的属性类型将取决于原始属性是否为对象类型。 If the original property is not an object type, the corresponding property will be boolean. 如果原始属性不是对象类型,则对应的属性将为布尔值。 If the original property is an object type, then the corresponding property will be a NestedFlags<> applied to that object type. 如果原始属性对象类型,则对应的属性将是应用于该对象类型的NestedFlags<>

This gives you the following behavior: 这使您具有以下行为:

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 ...

TypeScript complains about badActiveNestedColors , saying that more should not be a boolean . TypeScript抱怨badActiveNestedColors ,说more不应该是boolean

Hope that helps. 希望能有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM