简体   繁体   English

如何穷举typescript中的数组元素?

[英]How to exhaustive check the elements in an array in typescript?

Given that I can use a Record to make me not forget to type all options in an object鉴于我可以使用Record让我不会忘记在 object 中键入所有选项

type Country = "uk" | "france" | "india";

export const data: Record<Country, boolean> = {
  uk: true,
  france: true,
  // complains that india is not present, excellent!
};

how can I make so it complains the same way for arrays?我怎样才能让它以同样的方式抱怨 arrays?

export const data = [
  {value: "uk"},
  {value: "france"},
  // how to make typescript complain here that I forgot to add {value: "india"}?
];

Based on this answer , I think that this solves your problem:基于这个答案,我认为这可以解决您的问题:

type Country = "uk" | "france" | "india";

type MapOfKeysOf<U extends string> = {
    [key in U]: MapOfKeysOf<Exclude<U, key>>;
}

type ExhaustiveArrayOfObjects<Keys extends {[key: string]: {}}, T = {}, KeyName extends string = "value"> = {} extends Keys ? [] : {
    [key in keyof Keys]: [T & Record<KeyName, key>, ...ExhaustiveArrayOfObjects<Keys[key], T, KeyName>];
}[keyof Keys]

export const data: ExhaustiveArrayOfObjects<MapOfKeysOf<Country>> = [
    {
        value: 'uk',
    },
    {
        value: 'france',
    },
    {
        value: 'india',
    }
]

If you want, you can pass an extra type to extends or event customize the prop that will hold de value如果你愿意,你可以传递一个额外的类型来扩展或事件自定义将保持价值的道具

type Country = "uk" | "france" | "india";

type MapOfKeysOf<U extends string> = {
    [key in U]: MapOfKeysOf<Exclude<U, key>>;
}

type ExhaustiveArrayOfObjects<Keys extends {[key: string]: {}}, T = {}, KeyName extends string = "value"> = {} extends Keys ? [] : {
    [key in keyof Keys]: [T & Record<KeyName, key>, ...ExhaustiveArrayOfObjects<Keys[key], T, KeyName>];
}[keyof Keys]

type Option = {
    label: string,
    id: Country
}

const data: ExhaustiveArrayOfObjects<MapOfKeysOf<Country>, Option, "id"> = [
    {
        label: "United Kingdom",
        id: 'uk',
    },
    {
        label: "France",
        id: 'france',
    },
    {
        label: "India",
        id: 'india',
    }
]

const option: Option = data[0]

You can check more on this playgroud你可以在这个游乐场上查看更多

I am using some utility functions from a library but the it is total achievable without using one.我正在使用库中的一些实用函数,但它完全可以在不使用一个的情况下实现。 I actually got some help from stack overflow in order to come up with this solution haha... Credits to caTS Related question实际上,为了想出这个解决方案,我从堆栈溢出中得到了一些帮助哈哈...致谢caTS Related question

import { List, Union } from "ts-toolbelt";

type GetData<TCountries extends string[]> = List.Length<TCountries> extends 0
  ? []
  : List.Append<GetData<List.Pop<TCountries>>, {
    value: List.Last<TCountries>
  }>;

export const data : GetData<Union.ListOf<Country>> = [
  {value: "uk"},
  {value: "france"},
  // how to make typescript complain here that I forgot to add {value: "india"}?
];

I know it's ugly, but it's not factorial complexity and it does not require a helper function.我知道这很丑陋,但它不是阶乘复杂度,也不需要助手 function。

type Country = "uk" | "france" | "india";

const data = [
    { value: 'uk' },
    { value: 'france' },
    { value: 'india' }
] as const;

type test = IsExhaustive<typeof data>

type IsExhaustive<
    T extends Country extends Values ? unknown : { error: [Country, 'does not extend', Values] },
    Values =  keyof {
        [K in keyof T as T[K] extends {value: PropertyKey} ? T[K]['value'] : never]: never
    }
> = T

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

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