我有一个可以获取配置对象的类。我希望能够通过类公开的方法获取并设置值。
type ConfigValue = {name: string, value: string};
type Schema = {
[key: string]: {
someValue: boolean,
values: ConfigValue[]
}
}
class Config {
constructor(private config: Schema) { }
public getValue(key: string): ConfigValue {
// ...
}
public setValue(c: ConfigValue): void {
// ...
}
}
Now I create an instance of Config and pass the configuration:
const conf: Schema = {
'general': {
someValue: true,
values: [
{ 'name': 'title', 'value': 'Title' },
{ 'name': 'charset', 'value': 'utf-8' }
]
},
'http': {
someValue: boolean,
values: [
{ 'name': 'proxy', 'value': 'http://proxy' }
]
}
}
const c = new Config(conf);
c.getValue('proxy');
c.setValue('title', 'New Title');
实现这一点应该可以,但是当实现这两种方法时,我遇到了一个问题:我可以遍历Schema中的每个对象,然后遍历values数组。但是,如果我能以某种方式获得钥匙,那会容易得多。我想到了泛型,将Scheme直接传递给类,这两种方法都可以使用它,但是现在我被方法类型定义所困。我首先想到了这一点:
class Config<T extends Schema> {
constructor(private config: T) { }
public getValue<K extends keyof T>(key: K): T[K]['values'] {
return this.config[key].values;
}
…
}
K现在是字符串类型|数字(因为索引类型),而我的返回类型是T [K] [‘values’],即ConfigValues数组。但我的目标是,该键实际上是ConfigValue.name属性。我的返回类型也应该是ConfigValue类型。
public getValue<K extends keyof T>(key: string): T[K]['values'][??] {
return this.config[??].values[key];
}
我不知道这是否是故意的,我也不应该直接在定义中键入键(T [K]-> ['groups'] <-)。希望这不会引起混淆,任何帮助或想法都会得到赞赏!
答案 0 :(得分:0)
我认为TypeScript类型和JavaScript对象一团糟。请记住,TypeScript已转换为纯JavaScript。因此在程序执行期间将不存在任何类型。 TypeScript仅在编译期间起作用,而在执行期间消失。因此,无法使用TypeScrpt类型或泛型来提取某些数据或编写任何条件。类型仅用于检查是否将正确类型的参数传递给某个函数。
由于数组本质上是动态的(您可以在运行时添加/删除元素),因此无法键入检查数组内容。您不能依靠TypeScript来根据类型查找数组元素。
如果您希望ConfigValue.name
是密钥,则应首先重构Schema
。现在Schema
包含ConfigValue
的数组。除了迭代数组外,您无法提取数组的单个元素。如果可能,将配置存储为对象而不是数组。
仅当name
属性在值数组中唯一时,才能转换为对象。
例如
type Schema = {
[key: string]: {
someValue: boolean,
values: { [name: string]: ConfigValue }
}
}
现在getValue
看起来像
public getValue(key: string): ConfigValue {
let configItem = Object.keys(this.config).find(k => this.config[k].values[key] !== undefined);
return configItem.values[key];
}
根据您要传递config
作为密钥的要求,仍然需要遍历ConfigValue.name
个密钥。