检查对象成员的值是否与 TypeScript 泛型类型匹配。

huangapple go评论62阅读模式
英文:

Checking that the value of an object member matches a Typescript generic type

问题

Let's say I need to construct an object based on the potential values from a type. How would I go about narrowing that object down?

type Values = {
    foo: boolean,
    bar: string
}

type Properties<Type> = {
    name: keyof Type;
    // I want to narrow values so that it only accepts the matching value from Type
    values: Type[keyof Type][];
};

const properties: Properties<Values>[] = [
    {
        name: 'foo',
        // Should complain because 'false' !== boolean
        values: [true, 'false'],
    },
    {
        name: 'bar',
        // Should be ok
        values: ['hello', 'goodbye'],
    }
];

TypeScript playground

英文:

Let's say I need to construct an object based off the potential values from a type. How would I go about narrowing that object down?

type Values = {
    foo: boolean,
    bar: string
}

type Properties&lt;Type&gt; = {
    name: keyof Type;
    // I want to narrow values so that it only accepts the matching value from Type
    values: Type[keyof Type][];
};

const properties: Properties&lt;Values&gt;[] = [
    {
        name: &#39;foo&#39;,
        // Should complain because &#39;false&#39; !== boolean
        values: [true, &#39;false&#39;],
    },
    {
        name: &#39;bar&#39;,
        // Should be ok
        values: [&#39;hello&#39;, &#39;goodbye&#39;],
    }
];

TypeScript playground

答案1

得分: 4

你可以使用映射类型来实现这一点。

当前的问题是,基于可能的值创建了一个联合类型。如果你改为遍历键并按照需要创建输出类型,你将得到一个包含所有可能类型的对象类型。

然后,如果你使用 keyof Type 来索引映射类型,你可以获得正确映射的值。

一个类似这样的类型可以工作:

type Properties<Type> = {
    [K in keyof Type]: { name: K; values: Type[K][] };
}[keyof Type];

TS playground

更多细节请参考playground

英文:

you can use mapped types for this.

The issue is currently a union is created based on the possible value. If instead you map over the keys and create the output type as you want you end up with an object type with all possible types.

Then if you index the mapped type with keyof Type you can get the correctly mapped values.

A type like this can work

type Properties&lt;Type&gt; = {
    [K in keyof Type]: { name: K; values: Type[K][] };
}[keyof Type];

TS playground

More detail
playground

答案2

得分: 0

你可以编写一个只能通过验证类型的代码路径实例化的类。

英文:

You can write a class that is only instantiated by a code path that verifies the type

class Property&lt;Type&gt; {
  private name_: keyof Type;
  private values_: Type[keyof Type][]
  private constructor(name: keyof Type, values: Type[keyof Type][])
  {
    this.name_ = name;
    this.values_ = values;
  }
  get name(): keyof Type { return this.name_; }
  get values(): Type[keyof Type][] { return this.values_; }
  static make&lt;Type, K extends keyof Type&gt;(name: K, values: Type[K][]): Property&lt;Type&gt;{
    return new Property&lt;Type&gt;(name, values);
  }
};

TS playground

huangapple
  • 本文由 发表于 2023年4月14日 00:03:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76007544.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定