【问题标题】:Use type never with interface/class implementations in Typescript在 Typescript 中从不使用类型与接口/类实现
【发布时间】:2026-01-05 07:25:02
【问题描述】:

我想使用 typescript never 类型,以确保我已经检查了接口的所有可能实现。 Here is the code:

interface MyInterface {
    a: string;
    b: number;
}

class MyClass1 implements MyInterface {
    a: string;
    b: number;

    constructor() { }
}

class MyClass2 implements MyInterface {
    a: string;
    b: number;

    constructor() { }
}

function foo(arg: MyInterface) {
    if (arg instanceof MyClass1) {

    } else if (arg instanceof MyClass2) {

    } else {
        assertNever(arg);
    }
}

function assertNever(value: never): never {
  throw Error(`Unexpected value '${value}'`);
}

但我得到了错误:'MyInterface' 类型的参数不可分配给'never' 类型的参数。

有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: typescript class interface


    【解决方案1】:

    您可以使用assertNever 方法来确保处理所有案例(我猜这是您想要做的)。问题是您需要结合所有可能性而不是使用接口。 Typescript 无法知道接口的所有实现是什么,因此您的类型保护不会缩小参数的类型。

    这将按您的预期工作:

    function foo(arg: MyClass1 | MyClass2) {
        if (arg instanceof MyClass1) {
    
        } else if (arg instanceof MyClass2) {
    
        } else {
            assertNever(arg);
        }
    }
    

    【讨论】:

    • 太棒了!谢谢!
    【解决方案2】:

    我认为你永远不会误会。

    来自docs

    never 类型是每个类型的子类型,并且可以分配给每个类型;但是,没有类型是 never 的子类型或可分配给 never(never 本身除外)。甚至 any 也不能分配给 never。

    你不能给never赋值 由于你的类型声明是assertNever(value: never),调用assertNever(arg);时给它赋值时会报错

    只需将其更改为 assertNever(value: any): never 即可修复错误。 (或者如果你想要更具体的类型)

    【讨论】:

    • 是的,这就是重点,我想使用 never 类型来断言我已经检查了 MyInterface 的所有可能实现。如果我检查所有实现,我可以永远以“else”块结束...
    最近更新 更多