我正在定义一个具有通用功能的接口,例如:
export interface IState {
send: <I, E>(message: I, callback?: (e: E) => void) => IState;
}
它对于具有多个签名的类运行良好:
class Left implements IState {
send(m: 'go-on', cb?: (e: never) => void): Left;
send(m: 'turn-right', cb?: (e: never) => void): Right;
send(m: 'go-on' | 'turn-right', cb?: any) {
return m === 'go-on' ? new Left() : new Right();
}
}
class Right implements IState {
send(m: 'go-on', cb?: (e: never) => void): Right;
send(m: 'turn-left', cb?: (e: never) => void): Left;
send(m: 'go-on' | 'turn-left', cb?: any) {
return m === 'go-on' ? new Right() : new Left();
}
}
type Both = Left | Right;
function test(l: Both) {
if (l instanceof Left) {
l.send('turn-right')
.send('turn-left')
.send('turn-right')
.send('turn-left');
}
const l2 = new Left();
l2.send('go-on')
.send('turn-right')
.send('turn-left');
l2.send('turn-right').send('turn-left');
}
但是,当我想定义一个只有一个发送签名的IState时, 我遇到了编译错误:
class CountState implements IState {
constructor(public readonly data: number) {}
// send(m: 'inc', cb?: (e: number) => void): CountState;
// send(m: 'inc', cb?: (e: number) => void): CountState;
send(m: 'inc', cb?: (e: number) => void): CountState {
const result = this.data + 1;
if (cb !== undefined) {
cb(result);
}
return new CountState(this.data + 1);
}
}
发送方法出错:
类型为“ CountState”的属性“发送”不能分配给同一对象 基本类型为“ IState”的属性。输入'((m:“ inc”,cb ?:((e:number) =>无效)| undefined)=> CountState'不能分配给类型'(message:I,callback ?:((e:E)=> void)| undefined)=> IState'。 参数'm'和'message'的类型不兼容。 ts(2416)
不能将类型“ I”分配给类型“ inc”。
如果我添加这两个注释行,例如
class CountState implements IState {
constructor(public readonly data: number) {}
send(m: 'inc', cb?: (e: number) => void): CountState;
send(m: 'inc', cb?: (e: number) => void): CountState;
send(m: 'inc', cb?: (e: number) => void): CountState {
const result = this.data + 1;
if (cb !== undefined) {
cb(result);
}
return new CountState(this.data + 1);
}
}
它可以编译,但是看起来确实很奇怪。我该如何解决?
答案 0 :(得分:2)
我同意Titian Cernicova-Dragomir的观点,这似乎是编译器错误。 IState的定义基本上指出“发送”属性是一个可以用任何类型的“消息”调用的函数,而回调参数“ e”也可以具有任何类型。
export interface IState {
send: <I, E>(message: I, callback?: (e: E) => void) => IState;
}
同时,在示例用法中,您明确列出了可能的类型,这些类型与接口定义相矛盾。如果通过编译很奇怪。
class Left implements IState {
send(m: 'go-on', cb?: (e: never) => void): Left;
send(m: 'turn-right', cb?: (e: never) => void): Right;
send(m: 'go-on' | 'turn-right', cb?: any) {
return m === 'go-on' ? new Left() : new Right();
}
}
看看所包含的测试代码,无论如何,您都在检查未知的“两者”类型的确切类型,因此即使您只是在类中定义单独的方法,似乎也没有功能损失和正确的每个动作。 eq:
class Left {
turnRight(...) {
return new Right();
}
keepGoin(...) {
return new Left();
}
}
与对每个操作使用通用的“发送”方法相反。