我假设您使用的是 --strictNullChecks 编译器选项,如果您没有使用,那么您应该这样做。
我认为可选参数本身不是问题,但从您的使用情况来看,您似乎希望传递给addResource() 和createResource() 的ResourceConfig 对象的各个属性可能会丢失。但是这些方法的签名并没有这么说。这造成了一种情况,您必须尝试回避 TypeScript 的类型系统,而不是使用它。
具体来说,config = {} as ResourceConfig; 行有问题。您实际上使用type assertion 欺骗了编译器,因为空对象{} 不是ResourceConfig。有时对编译器的善意的谎言很有用,特别是如果它们只是临时的(例如,如果在那一行之后你继续在一个最初为空的对象中设置所有属性)。但是在这种情况下,您永远不会填充config 的属性,因此欺骗传递到createResource() 方法...其中amount、profit 和load 变量被编译器认为是@ 987654337@ 但实际上在运行时可能是undefined。您可以通过检查falsiness 的每个值来处理这种可能性,但如果我相信类型系统,这似乎是不必要的。
有不同的方法来处理这个问题。一种是说如果config 缺少某些属性也没关系。这意味着您实际上拥有Partial<ResourceConfig>,而不是处理ResourceConfig,其中Partial<T> 是标准库中的mapped type,其definition 是
type Partial<T> = { [P in keyof T]?: T[P] };
所以Partial<ResourceConfig> 等价于
{
amount?: number;
profit?: number;
load?: number;
}
使用它,你会得到:
public addResource(config?: Partial<ResourceConfig>): void {
if (!config) {
config = {}; // truth
}
const resource: FormGroup = this.createResource(config);
this.control.push(resource);
}
private createResource({ amount, profit, load }: Partial<ResourceConfig>): FormGroup {
return new FormGroup({
amount: new FormControl(amount || 1),
profit: new FormControl(profit || 1),
load: new FormControl(load || 1)
});
}
不需要类型断言,编译器知道createResource中的变量是number | undefined,传递给FormControl构造函数的参数也知道是number,因为|| 1 把戏。
解决此问题的另一种方法是实际要求config 是ResourceConfig | undefined,如果未定义,则为其分配一个有效的ResourceConfig:
public addResource(config?: ResourceConfig): void {
if (!config) {
config = {
amount: 1,
profit: 1,
load: 1
};
}
const resource: FormGroup = this.createResource(config);
this.control.push(resource);
}
private createResource({ amount, profit, load }: ResourceConfig): FormGroup {
return new FormGroup({
amount: new FormControl(amount),
profit: new FormControl(profit),
load: new FormControl(load)
});
}
这让createResource() 不必担心可能出现的undefined 变量。如果您想让amount、profit 或load 为零,这种方式可能会更好。注意0 || 1 等于1,因为0 是假的。如果您不想让0 神奇地变成1,则不能使用|| 1 技巧。
无论哪种方式都可以,并且存在许多其他解决方案。这里的主要思想是尝试利用 TypeScript 的类型系统而不是规避它。
好的,希望对您有所帮助。祝你好运!