简体   繁体   English

打字稿-根据提供的对象键检测值类型

[英]Typescript - Detect value types based on the object key provided

Given I have a type like: 鉴于我有一个像这样的类型:

type Foo = {
  foo: number;
  bar: string;
  baz: boolean;
}

I want to have a type Buzz which can detect the value type against a key, ie 我想有一个Buzz类型,它可以根据键检测值类型,即

const abc: Buzz<Foo> = {
  key: 'foo',
  formatter: (detectMe) => {} //I want TS to infer this to be 'number'
};

Given the key 'foo' the argument in formatter should be inferred to be number . 给定键“ foo”,格式化程序中的参数应推断为number I tried this: 我尝试了这个:

interface ColumnDescription<T> {
  label: string;
  key: keyof T;
  formatter?: (datum: T[keyof T]) => void;
}

However this results in the argument being inferred to be number | string | boolean 但是,这导致将参数推断为number | string | boolean number | string | boolean number | string | boolean . number | string | boolean

Tried this as well: 也尝试过这个:

interface ColumnDescription<T, K extends keyof T> {
  label: string;
  key: K;
  formatter?: (datum: T[K]) => void;
}

This sort of works but I always need the specify the key in the second type argument, instead of it happening automatically. 这种工作,但是我总是需要在第二个类型参数中指定键,而不是自动发生。 ie: 即:

const abc: Buzz<Foo, 'foo'> = { //I don't want to specify the key
  key: 'foo',
  formatter: (detectMe) => {} //This is inferred correctly
};

As in my comment, I'd suggest 正如我的评论,我建议

type Buzz<T> = {
  [K in keyof T]-?: { key: K; formatter: (d: T[K]) => void }
}[keyof T];

which is similar to what you did with Buzz<T, K extends keyof T> , but instead of making Buzz need K to be specified, I used a mapped type {[K in keyof T]: ...} which automatically iterates over keys in keyof T and makes a new object with the same keys but whose property values are the types you're looking for. 这类似于您对Buzz<T, K extends keyof T>所做的操作Buzz<T, K extends keyof T> ,但是我没有使Buzz需要指定K ,而是使用了一个自动迭代的映射类型 {[K in keyof T]: ...}keyof T中使用keyof T并使用相同的键创建一个新对象,但是其属性值是您要查找的类型。 That means to get the desired Buzz<T> we need to look up the property values, by indexing into it with [keyof T] . 这意味着要获得所需的Buzz<T>我们需要通过使用[keyof T]对其进行索引来查找属性值。 That makes Buzz<T> a union of types, where each constituent of the union corresponds to your Buzz<T, K extends keyof T> for a particular key K 这使得Buzz<T>成为类型的并集,其中并集的每个组成部分都对应于您的Buzz<T, K extends keyof T>针对特定键K Buzz<T, K extends keyof T>

Let's make sure it works: 让我们确保它起作用:

const abc: Buzz<Foo> = {
  key: "foo",
  formatter: detectMe => {} // inferred as number, as desired
};

Looks good, and let's inspect the type of abc with IntelliSense: 看起来不错,让我们使用IntelliSense检查abc的类型:

const abc: {
    key: "foo";
    formatter: (d: number) => void;
} | {
    key: "bar";
    formatter: (d: string) => void;
} | {
    key: "baz";
    formatter: (d: boolean) => void;
}

That looks good too. 看起来也不错。

Okay, hope that helps; 好的,希望能有所帮助; good luck! 祝好运!

Link to code 链接到代码

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

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