我想在我的课程中要求一种或另一种构造函数:
const instance: MyClass = new MyClass({ digit: 5 });
...或...
const instance: MyClass = new MyClass({ letter: 'x' });
它不能同时是两个,也不能是其他一些对象。
此刻我有这个:
interface MyClassConstructor {
digit?;
letter?;
}
interface MyClassDigit extends MyClassConstructor {
digit: number;
}
interface MyClassLetter extends MyClassConstructor {
letter: string;
}
class MyClass {
constructor(obj: MyClassDigit | MyClassLetter) {
if (obj.digit) {
// ...
} else if (obj.letter) {
// ...
}
}
}
但是我不认为这样做是正确的方式...
答案 0 :(得分:1)
对于您的解决方案,我不会做太多改变。我不会同时具有两个属性的基本接口。我只需要使用一个联合和一个in
类型防护:
interface MyClassDigit {
digit: number;
}
interface MyClassLetter {
letter: string;
}
class MyClass {
constructor(obj: MyClassDigit | MyClassLetter) {
if ('digit' in obj) {
// obj is MyClassDigit
} else {
// obj is MyClassLetter
}
}
}
如果您有更多参数并且只需要一个成员,则可以使用条件类型自动生成类型:
interface MyParams {
digit?: number;
letter?: string;
}
type RequireOne<T> = (keyof T) extends infer K ?
K extends keyof T ?
Required<Pick<T, K>> : never : never
class MyClass {
constructor(obj: RequireOne<MyParams>) {
if ('digit' in obj) {
// obj has digit
} else {
// obj has letter
}
}
}
答案 1 :(得分:1)
重载constructor
:
interface WithDigit {
digit: number
}
interface WithLetter {
letter: string
}
class MyClass {
constructor(options: WithDigit);
constructor(options: WithLetter);
constructor(options: WithLetter | WithDigit) {
if ('digit' in options) {
/* */
}
if ('letter' in options) {
/* */
}
}
}
这将确保只接受一个。
new MyClass({ digit: 0 }); // OK
new MyClass({ letter: 'a' }); // OK
new MyClass({ digit: 0, letter: 'a' }); // Error