我想编写一个接受一些参数的函数,它们应该是可选的,但如果它们存在,那么我希望其他参数是必需的。
这是一个非常愚蠢的例子:
type PersonInfo = {
name: string;
age: number;
pets?: boolean;
petNames?: string[];
}
const recordPersonInfo = (options: PersonInfo) => {
database.save(options);
}
所以 pets
属性可以省略,但如果它是 true
那么我希望 petNames
是必需的。我如何告诉 Typescript 这样做?
答案 0 :(得分:3)
你可以使用联合类型:pets
属性是一个判别式,所以如果你写 if(options.pets)
那么在 if
块内,options
将被缩小到确定拥有 petNames
属性。
type PersonInfo = {
name: string;
age: number;
} & ({
pets?: false;
} | {
pets: true;
petNames: string[];
})
const recordPersonInfo = (options: PersonInfo) => {
database.save(options);
}
答案 1 :(得分:0)
利用函数重载,你可以这样做:
type PersonInfoWithPets = PersonInfo & { pets: true; petNames: string[] };
type PersonInfoWithoutPets = PersonInfo & { pets?: false; petNames?: undefined };
function recordPersonInfo(options: PersonInfoWithPets): void;
function recordPersonInfo(options: PersonInfoWithoutPets): void;
function recordPersonInfo(options: PersonInfo): void {
}
recordPersonInfo({
name: 'name',
age: 0,
});
recordPersonInfo({
name: 'name',
age: 0,
pets: false,
});
recordPersonInfo({
name: 'name',
age: 0,
pets: true,
petNames: [],
});
// This errors because `pets` but no `petNames`
recordPersonInfo({
name: 'name',
age: 0,
pets: true,
});
// This errors because `petNames` but no `pets`
recordPersonInfo({
name: 'name',
age: 0,
petNames: ['hi'],
});
// NOTE: This also errors because `pets` is a boolean here, not strictly true/false
recordPersonInfo(null! as PersonInfo);
老实说,TypeScript 并没有为此提供完美的解决方案。在这种特定情况下,您当然可以说“petNames
的存在(和空虚)应该取代对 pets
字段的需要”。在这种情况下,我们避开了两个重载,但更复杂的情况可能会导致需要更多的重载。
当然,您可以正确地记录函数,如果仍然给出错误的输入,则抛出错误。