简体   繁体   English

Typescript generics,使用泛型字段作为映射类型

[英]Typescript generics, use field of generic as mapped type

Horrible title, I know.可怕的标题,我知道。 I'm not sure how to describe this concisely.我不知道如何简明扼要地描述这一点。

I'm trying to make a function which takes an array of objects, each with a 'type' field, and a set of functions that handle the various types.我正在尝试制作一个 function 对象数组,每个对象都有一个“类型”字段,以及一组处理各种类型的函数。

The code below is my attempt at what I'm doing:下面的代码是我正在做的尝试:

You can see the object I'm trying to describe in the call to handler.您可以在对处理程序的调用中看到我试图描述的 object。

type Foo = {type: "foo", name: string}
type Bar = {type: "bar", score: number}

type Props<T extends {type: string}> = {
  variables: T[];
  functions: {
    [k in T["type"]]: (args: T) => void;
  }
}

function handler<T extends {type: string}>({variables, functions}: Props<T>) {
  variables.forEach(v => {
    functions[v.type](v); 
    // ^^^^^^^^^^^^^
    // No index signature with a parameter of type 'string' was found on type '{ [k in T["type"]]: (args: T) => void; }'.
  })
}

handler({
  variables: [{type: "foo", name: ""}, {type: "bar", score: 0}],
  functions: {
    "foo": (args) => {args.name}, // <--- args has type Foo | Bar, ideally would just be Foo
    "bar": (args) => {args.score},
  }
})

I'm not sure where I'm going wrong, any help would be greatly appreciated.我不确定我哪里出错了,任何帮助将不胜感激。

you can set the key as string in your Props type definition您可以在 Props 类型定义中将键设置为字符串

type Props<T extends {type: string}> = {
  variables: T[];
  functions: {
    [k in T["type"] as string]: (args: T) => void;
  }
}

However, you have noticed that you do not use your Foo and Bar types in your code.但是,您注意到您没有在代码中使用 Foo 和 Bar 类型。 Using them as follows throws an error that shows that there is something wrong in your design.如下使用它们会引发错误,表明您的设计中有问题。

type Foo = {type: "foo", name: string}
type Bar = {type: "bar", score: number}

type Props<T extends {type: string}> = {
  variables: T[];
  functions: {
    [k in T["type"] as string]: (args: T) => void;
  }
}

function handler<T extends {type: string}>({variables, functions}: Props<T>) {
  variables.forEach(v => {
    functions[v.type](v); 
    
  })
}

handler<Foo | Bar>({
  variables: [{type: "foo", name: ""}, {type: "bar", score: 0}],
  functions: {
    "foo": (args:Foo) => {args.name}, // <--- error here as name is not in Bar
    "bar": (args:Bar) => {args.score}, // <--- error here as name is not in Foo
  }
})

I would suggest to change your definition of Props我建议改变你对道具的定义

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

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