如何为这些对象定义接口:
let bob = {
Bob: {
age: 9,
gender: 'M'
}
};
let alice = {
Alice: {
age: 12,
gender: 'F'
}
};
我可以使用来自this thread的解决方案,但它过于宽松,我想将该用例限制为唯一(或固定数量)的密钥。
BONUS 如果你能弄清楚如何表达:
像这样的伪代码:
interface funnyEdge {
<string>from: fromEdge,
<string>to: toEdge
}
let edge: funnyEdge = {foo: {...}, bar: {...}}
答案 0 :(得分:2)
TypeScript中的类型系统不允许您指定具有指定数量的未指定键的类型。实际上,由于它缺少exact types,因此TypeScript实际上不允许您指定具有指定数量的指定键的类型。它只对对象文字进行过多的属性检查。作为一种类型,如:
type Person = {
age: number,
gender: 'M' | 'F' | 'O'
}
并不意味着Person
不能拥有其他密钥,例如:
const pirate = {
age: 35,
gender: 'M' as 'M',
legs: 1,
parrot: true
};
const piratesArePeopleToo: Person = pirate; // no problem
所以你最希望的是,如果传入一个包含太多键的对象文字,TypeScript会抱怨,如:
const otherPirate: Person = {
age: 40,
gender: 'F',
eyes: 1,
parrot: false
}; // error
不,就我所知,TypeScript不会让你表达这种约束。
我能想到的最好的解决方法是:创建一个带有单个键和Person
的函数,并返回所需类型的对象:
type NamedPerson<K extends string> = Record<K, Person>;
function makeNamedPerson<K extends string>(key: K, person: Person): NamedPerson<K> {
let namedPerson = {} as NamedPerson<K>;
namedPerson[key]=person;
return namedPerson;
}
const namedPerson = makeNamedPerson('chris', { age: 10, gender: 'O' });
console.log(namedPerson.chris.age);
如果组织代码,那么获取类型NamedPerson<K>
的对象的唯一合理方法是调用函数makeNamedPerson()
(例如,仅导出函数并生成它生成类的类型一个private
成员),然后你知道每个人都有一个密钥。这对于你来说并不像类型系统那样强制实施,但至少你使你的库用户难以规避约束。
希望有所帮助;祝你好运!
答案 1 :(得分:1)
喜欢这个吗?
interface Person {
age: number;
gender: "M" | "F";
}
interface Bob extends Person {
//...
}
interface Alice extends Person {
//...
}
interface Members {
Bob?: Bob;
Alice?: Alice;
}
let bob: Members = {
Bob: {
age: 9,
gender: 'M'
}
};
let alice: Members = {
Alice: {
age: 12,
gender: 'F'
}
};
alert(alice.Alice.age) // ok
alice.Bob = bob.Bob // ok
alert(alice.Eve.age) // error
答案 2 :(得分:1)
这个怎么样?
type Person<TName extends string> = {
[key in TName]: {
age: number,
gender: 'M'|'F'
}
};
var alice: Person<"Alice">;
alice.Alice.age = 42;
alice.AnythingElse // error;
多个键:
var johnAndMary: Person<"John" | "Mary">;
johnAndMary.John.age;
johnAndMary.Mary.gender;
johnAndMary.Don // error
答案 3 :(得分:0)
原来现在有办法做到这一点:
type Peeps = 'Bob'|'Alice';
type Def = { ... };
type Person = {[name in Peeps]?: Def }
// or if you're so inclined
type Person = Map<Peeps,Def>
// here with the other example
type EdgeEnd = 'from'|'to';
type FunnyNode = { ... };
type FunnyEdge = {[end in EdgeEnd]: FunnyNode};