我想写一个函数,接受一些参数,它们应该是可选的,但如果它们存在,那么我希望需要其他参数。
这里有一个非常愚蠢的例子:
type PersonInfo = {
name: string;
age: number;
pets?: boolean;
petNames?: string[];
}
const recordPersonInfo = (options: PersonInfo) => {
database.save(options);
}
所以pets
属性可以省略,但如果它是true
,那么我希望petNames
是必需的。我如何告诉Typescript这样做?
您可以使用并集类型:pets
属性是一个判别式,因此如果您在if
块中写入if(options.pets)
,则options
将缩小为肯定具有petNames
属性。
type PersonInfo = {
name: string;
age: number;
} & ({
pets?: false;
} | {
pets: true;
petNames: string[];
})
const recordPersonInfo = (options: PersonInfo) => {
database.save(options);
}
利用函数重载,您可以执行以下操作:
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并不能提供一个完美的解决方案。在这种特定的情况下,你可以说";CCD_ 9的存在(和空(应该取代对CCD_;当然在这种情况下,我们躲过了两次过载,但更复杂的情况可能会导致需要更多的过载。
当然,您可以正确地记录函数,并在仍然给出错误输入时抛出错误。