TypeScript何时使用结构化类型?

问题描述 投票:2回答:1

给出下面的类型,为什么编译器允许下面的赋值?我猜想它与在某些情况下使用结构化类型的TypeScript有关(即,由于SuccessFailure在结构上是等效的,因此编译器将它们视为可互换的),但是我想我不清楚在什么情况下结构化键入使用。

////////////////////
// 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的解决方案是为类型提供不同的字段(即svaluefvalue)。这可行,但是我希望接口是相同的,因此我选择了以下使用符号区分类的解决方案(如果遇到相关问题,请输入提示音):

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);
    }
}
typescript type-inference structural-typing
1个回答
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>] >

© www.soinside.com 2019 - 2024. All rights reserved.