英文:
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'],
}
];
英文:
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<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'],
}
];
答案1
得分: 4
你可以使用映射类型来实现这一点。
当前的问题是,基于可能的值创建了一个联合类型。如果你改为遍历键并按照需要创建输出类型,你将得到一个包含所有可能类型的对象类型。
然后,如果你使用 keyof Type
来索引映射类型,你可以获得正确映射的值。
一个类似这样的类型可以工作:
type Properties<Type> = {
[K in keyof Type]: { name: K; values: Type[K][] };
}[keyof Type];
更多细节请参考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<Type> = {
[K in keyof Type]: { name: K; values: Type[K][] };
}[keyof Type];
More detail
playground
答案2
得分: 0
你可以编写一个只能通过验证类型的代码路径实例化的类。
英文:
You can write a class that is only instantiated by a code path that verifies the type
class Property<Type> {
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<Type, K extends keyof Type>(name: K, values: Type[K][]): Property<Type>{
return new Property<Type>(name, values);
}
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论