TypeScript array to string literal type

后端 未结 3 1487
迷失自我
迷失自我 2020-11-27 13:08

I currently have both an array of strings and a string literal union type containing the same strings:

const furniture = [\'chair\', \'table\', \'lamp\'];
ty         


        
相关标签:
3条回答
  • 2020-11-27 13:18

    This answer is out of date, see answer above.

    The best available workaround:

    const furnitureObj = { chair: 1, table: 1, lamp: 1 };
    type Furniture = keyof typeof furnitureObj;
    const furniture = Object.keys(furnitureObj) as Furniture[];
    

    Ideally we could do this:

    const furniture = ['chair', 'table', 'lamp'];
    type Furniture = typeof furniture[number];
    

    Unfortunately, today furniture is inferred as string[], which means Furniture is now also a string.

    We can enforce the typing as a literal with a manual annotation, but it brings back the duplication:

    const furniture = ["chair", "table", "lamp"] as ["chair", "table", "lamp"];
    type Furniture = typeof furniture[number];
    

    TypeScript issue #10195 tracks the ability to hint to TypeScript that the list should be inferred as a static tuple and not string[], so maybe in the future this will be possible.

    0 讨论(0)
  • 2020-11-27 13:22

    Update for TypeScript 3.0 :

    With the use of generic rest parameters, there is a way to correctly infer string[] as a literal tuple type and then get the union type of the literals.

    It goes like this:

    const tuple = <T extends string[]>(...args: T) => args;
    const furniture = tuple('chair', 'table', 'lamp');
    type Furniture = typeof furniture[number];
    

    More about generic rest parameters

    Update for TypeScript 3.4:

    TypeScript version 3.4 has introduced so-called const contexts, which is a way to declare a tuple type as immutable and get the narrow literal type directly (without the need to call a function like shown above).

    With this new syntax, we get this nice concise solution:

    const furniture = ['chair', 'table', 'lamp'] as const;
    type Furniture = typeof furniture[number];
    

    More about the new const contexts is found in this PR as well as in the release notes.

    0 讨论(0)
  • 2020-11-27 13:23

    The only adjustement I would suggest is to make the const guaranteed compatible with the type, like this:

    type Furniture = 'chair' | 'table' | 'lamp';
    
    const furniture: Furniture[] = ['chair', 'table', 'lamp'];
    

    This will give you a warning should you make a spelling error in the array, or add an unknown item:

    // Warning: Type 'unknown' is not assignable to furniture
    const furniture: Furniture[] = ['chair', 'table', 'lamp', 'unknown'];
    

    The only case this wouldn't help you with is where the array didn't contain one of the values.

    0 讨论(0)
提交回复
热议问题