我想创建一个识别嵌套对象的字符串的类型。但是,尝试这样做只会给我返回类型string
而不是特定字符串数组。实施此方法的正确方法是什么?请参见下面的代码。谢谢!
interface SampleInterface {
allIds: string[];
byId: {
[key: string]: string[];
};
}
const sampleObject: SampleInterface = {
allIds: [
'foo',
'bar',
'alpha',
'bravo',
'charlie',
],
byId: {
foo: ['hello world'],
bar: ['hello world'],
alpha: ['hello world'],
bravo: ['hello world'],
charlie: ['hello world'],
},
};
type ObjectKeys = keyof typeof sampleObject.byId;
// desired: type ObjectKeys = 'foo' | 'bar' | 'alpha' | 'bravo' | 'charlie';
// actual: type ObjectKeys = string;
const fn = (x: ObjectKeys) => console.log(x);
fn('test'); // no error is returned
答案 0 :(得分:2)
sampleObject
的类型为SampleInterface
,因为这是您为其提供的类型注释。因此sampleObject.byId
的类型为{ [key: string]: string[] }
,因为这是您定义接口的方式。因此keyof typeof sampleObject.byId
是string
。
直接的解决方案是声明sampleObject
而不使用类型注释,从而使编译器尽可能具体地推断其类型。
也就是说,最好也将SampleInterface
设为通用,以便类型检查器强制allIds
中的字符串与byId
的属性名称相同。如果要让常量的类型使用SampleInterface
,则无需重复代码的最佳方法是首先声明byId
对象,根据该对象的键声明ObjectKeys
类型,然后然后使用Object.keys()动态创建allIds
数组。
interface SampleInterface<K extends PropertyKey> {
allIds: K[];
byId: Record<K, string[]>
}
const _sampleObjectById = {
foo: ['hello world'],
bar: ['hello world'],
alpha: ['hello world'],
bravo: ['hello world'],
charlie: ['hello world'],
};
// ObjectKeys = 'foo' | 'bar' | 'alpha' | 'bravo' | 'charlie'
type ObjectKeys = keyof typeof _sampleObjectById;
const sampleObject: SampleInterface<ObjectKeys> = {
allIds: Object.keys(_sampleObjectById) as ObjectKeys[],
byId: _sampleObjectById
}
// logs ['foo', 'bar', 'alpha', 'bravo', 'charlie']
console.log(sampleObject.allIds);