如何根据数组的值定义类型?

Fre*_*ind 7 typescript typescript-typings

如果我有一个看起来像数组的类型:

type names = ['Mike', 'Jeff', 'Ben'];
Run Code Online (Sandbox Code Playgroud)

我可以很容易地定义另一种类型,它具有以下项目的值names

type UserName = names[number]
Run Code Online (Sandbox Code Playgroud)

对于函数:

function hello(name: UserName) {
  console.log(`Hello, ${name}!`)
}
Run Code Online (Sandbox Code Playgroud)

我只能传递一个MikeJeffBen发挥作用hello。如果我提供其他值,例如John,则无法编译。

如果我没有type names而是const 数组 names怎么办?

const names = ['Mike', 'Jeff', 'Ben'];

type UserName = ???;

function hello(name: UserName) {
  console.log(`Hello, ${name}!`)
}

hello('Mike');
Run Code Online (Sandbox Code Playgroud)

是否可以定义这样的类型UserName

jca*_*alz 8

In TypeScript 3.4, which should be released in March 2019 it will be possible to tell the compiler to infer the type of a tuple of string literals as a tuple of string literals, instead of as string[], by using the as const syntax. It should look like this:

const names = ['Mike', 'Jeff', 'Ben'] as const; // TS3.4 syntax
type Names = typeof names; // type Names = readonly ['Mike', 'Jeff', 'Ben'] 
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
Run Code Online (Sandbox Code Playgroud)

Until then (in TypeScript 3.0 through 3.3) you can get this effect by using a helper function which gives the compiler hints to infer a narrower type:

type Narrowable = string | number | boolean | undefined | null | void | {};
const tuple = <T extends Narrowable[]>(...t: T)=> t;
const names = tuple('Mike', 'Jeff', 'Ben');

type Names = typeof names; // type Names = ['Mike', 'Jeff', 'Ben'] 
type UserName = Names[number]; // 'Mike' | 'Jeff' | 'Ben'
Run Code Online (Sandbox Code Playgroud)

(Note that in both cases you can skip the intermediate Names type and just define type UserName = (typeof names)[number] if you prefer)

Okay, hope that helps. Good luck!