我真的不知道我想要的是否可能。我已经尝试了一段时间,但现在我放弃并向社区寻求帮助。
我想要一个像这样的配置对象:
const someConfig: ParameterDescriptions = {
someNumProperty: {
name: 'numPropert',
type: 'number',
defaultValue: 42,
},
someStrProperty: {
name: 'strPropert',
type: 'string',
defaultValue: 'some default value',
},
someBoolProperty: {
name: 'boolProperty',
type: 'boolean',
defaultValue: false,
},
};
然后像这样的对象:
interface MyState {
someNumProperty: number;
someStrProperty: string;
someBoolProperty: boolean;
}
我想强制MyState
具有与someConfig
相同的属性,但使用每个ParameterDesc
的类型属性中提到的类型
ParameterDescriptions
看起来像这样:
export interface BaseParameterDesc {
name: string;
}
export interface NumberParameterDesc extends BaseParameterDesc {
type: 'number';
defaultValue?: number;
}
export interface StringParameterDesc extends BaseParameterDesc {
type: 'string';
defaultValue?: string;
}
export interface BooleanParameterDesc extends BaseParameterDesc {
type: 'boolean';
defaultValue?: boolean;
}
export type ParameterDesc =
NumberParameterDesc|StringParameterDesc|BooleanParameterDesc;
export type ParameterDescriptions = {
[key: string]: ParameterDesc;
};
但我不知道如何建立MyState
与ParameterDescription
实例之间的关系。
我的一个想法是让MyState实现一些尝试强制执行此操作的State类型,但它确实不起作用
type State<PDesc extends ParameterDescriptions> = {
// The .type at the end does not work, but I don't know
// of alternatives
[property in keyof PDesc]: PDesc[property].type;
};
有什么想法吗?或者这是不可能的?
此帖子中的所有代码均可在此Typescript Playground
中找到答案 0 :(得分:1)
我们需要解决的第一个问题是,您定义someConfig
的方式实际上不会保留属性名称,它最终将成为可由任何字符串索引的变量。如果我们使用通用辅助函数,我们可以轻松地强制执行ParameterDescriptions
的约束并保留实际的密钥生成:
function createConfig<T extends ParameterDescriptions>(c: T): T {
return c;
}
const someConfig = createConfig({
someNumProperty: {
name: 'numPropert',
type: 'number',
defaultValue: 42,
},
someStrProperty: {
name: 'strPropert',
type: 'string',
defaultValue: 'some default value',
},
someBoolProperty: {
name: 'boolProperty',
type: 'boolean',
defaultValue: false,
},
});
现在someConfig
保留了关键名称,我们可以使用与您类似的方法,只是不能直接使用type
属性作为类型,我们需要一个额外的类型来映射类型名称和类型(我们也可以使用条件类型,但在这种情况下这似乎更简单)
type TypeNamesToTypes = {
boolean: boolean;
string: string;
number: number;
}
type State<T extends ParameterDescriptions> = { [P in keyof T]: TypeNamesToTypes[T[P]['type']]}
type MyState = State<typeof someConfig> // same as = {someNumProperty: number;someStrProperty: string;someBoolProperty: boolean;}
游乐场link