给出以下类型,为什么编译器允许下面的赋值?我猜想它与在某些情况下使用结构化类型的TypeScript有关(即,由于Success
和Failure
在结构上是等效的,因此编译器将它们视为可互换的),但是我想在以下情况下我不清楚使用什么类型的结构类型。
////////////////////
// Types
////////////////////
class Success<S> {
constructor(public value: S) { }
static create<S, F>(value: S):Result<S, F> {
return new Success<S>(value);
}
}
class Failure<F> {
constructor(public value: F) {}
static create<S, F>(value: F): Result<S, F> {
return new Failure<F>(value);
}
}
type Result<S, F> = Success<S> | Failure<F>;
////////////////////
// Usage
////////////////////
/*
How is the assignment below allowed by the compiler?
Failure.create produces a Result<unknown, number> which should not
be assignable to a Result<number, Error>
*/
const f: Result<number, Error> = Failure.create(2);
对于犯罪分子的额外上下文:
正如Malvolio指出的那样,问题是类型联合是可交换的,而解决方法是使类型在结构上不相等。 Malavolio的解决方案是为类型提供不同的字段(即svalue
和fvalue
)。可以,但是我更喜欢使用相同的接口,因此我选择了以下使用符号区分类的解决方案(如果遇到相关问题,请输入提示音):
export const SuccessType = Symbol();
export class Success<S> {
public readonly resultType = SuccessType;
private constructor(public value: S) {}
static create<S, F>(value: S): Result<S, F> {
return new Success<S>(value);
}
}
export const FailureType = Symbol();
export class Failure<F> {
public readonly resultType = FailureType;
private constructor(public value: F) {}
static create<S, F>(value: F): Result<S, F> {
return new Failure<F>(value);
}
}
答案 0 :(得分:2)
哇。这非常微妙,但是请尝试以下方法:
class Success<S> {
constructor(public svalue: S) { }
static create<S, F>(value: S):Result<S, F> {
return new Success<S>(value);
}
}
class Failure<F> {
constructor(public fvalue: F) {}
static create<S, F>(value: F): Result<S, F> {
return new Failure<F>(value);
}
}
type Result<S, F> = Success<S> | Failure<F>;
const f: Result<number, Error> = Failure.create(2);
根据定义,您的Result<S, F>
是具有类型value
的属性S | F
的任何东西。因此,Result<S, F>
可分配给Result<F, S>
—类型联合是可交换的。
在我的版本中,Result<S, F>
具有类型为svalue
的属性S
或类型为fvalue
的属性F
,所以Result<S, F>
无法分配给Result<F, S>