从联合类型创建类似记录的类型

Wes*_*den 4 typescript typescript-typings

在 Typescript 中,我创建了一个具有共享“type”属性的联合类型:

export type Instruction =
  | { type: 'local.set', name: string, value: Expression }
  | { type: 'i32.const', value: number }
  | { type: 'i32.add', left: Expression, right: Expression };
Run Code Online (Sandbox Code Playgroud)

我想创建一个对象,其中“type”属性的值作为键,函数作为值。就像这样:

const visitor: Record<Instruction['type'], (instruction: Instruction) => void> = {
   'local.set': (instruction) => {},
   'i32.const': (instruction) => {},
   'i32.add': (instruction) => {},
}
Run Code Online (Sandbox Code Playgroud)

但“指令”参数的输入对我来说太通用了。我想知道我可以通过函数内的指令访问哪些属性。那么如何创建一个Record类似的类型,其中包含类型中“type”属性的所有键Instruction,以及它们各自的Instruction类型作为值?

换句话说; 如果我这样做,Typescript 可以推断出类型:

const instruction: Instruction = { type: 'local.set' }; // TS knows about the missing 'name' and 'value' properties
Run Code Online (Sandbox Code Playgroud)

但我想做一些类似的事情:

const instruction: Instruction[where type = 'local.set'] = { type: 'local.set' };
Run Code Online (Sandbox Code Playgroud)

这可能吗?如何实现?

Tit*_*mir 8

您可以使用自定义映射类型来映射...的并集type,然后使用Extract条件类型从中获取Instruction与当前属性具有相同类型的并集组成部分:

export type Instruction =
    | { type: 'local.set', name: string, value: Expression }
    | { type: 'i32.const', value: number }
    | { type: 'i32.add', left: Expression, right: Expression };

type Visitor<T extends { type: string}> = {
    [P in T['type']]: (instruction: Extract<T, { type: P }>) => void
}
const visitor: Visitor<Instruction> = {
    'local.set': (instruction) => { instruction.name},
    'i32.const': (instruction) => { instruction.value },
    'i32.add': (instruction) => {  instruction.right },
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接