【问题标题】:Convert interface with nullable string property to string property将具有可为空字符串属性的接口转换为字符串属性
【发布时间】:2021-06-15 15:17:31
【问题描述】:

我有以下两个接口,一个允许可以为空的vin,另一个不允许:

interface IVehicle {
    vin: string | null;
    model: string;
}

interface IVehicleNonNullVin {
    vin: string;
    model: string;
}

我希望能够在我能够推断出vin 不是null 的执行路径中将模型从IVehicle 转换为IVehicleNonNullVin

考虑这个例子:

const myVehicle: IVehicle = {
    vin: 'abc123',
    model: 'm3'
};

const needsVin = (_: IVehicleNonNullVin) => false;

if (myVehicle.vin === null) {
    throw new Error('null');
} else {
    needsVin(myVehicle);
 // ~~~~~~~~~~~~~~~~~~~ 'IVehicle' is not assignable to 'IVehicleNonNullVin'
}

返回以下错误:

“IVehicle”类型的参数不能分配给“IVehicleNonNullVin”类型的参数。
属性“vin”的类型不兼容。
键入'字符串 | null' 不可分配给类型 'string'。
类型 'null' 不能分配给类型 'string'。

即使我是肯定的,这里的属性也不能为空。

:如何通过代码流中的类型检查让TS相信现有模型符合类型?

Demo in TS Playground


解决方法

作为一种解决方法,我可以强制转换类型(但这会忽略现有的类型安全性):

needsVin(myVehicle as IVehicleNonNullVin);

或者建立一个新模型(但这不能很好地扩展很多属性):

const nonNullVehicle: IVehicleNonNullVin = {
    model: myVehicle.model,
    vin: myVehicle.vin
}
needsVin(nonNullVehicle);

【问题讨论】:

    标签: typescript typescript4.0


    【解决方案1】:

    您可以使用type predicate 来定义用户定义的类型保护,如下所示:

    const isNonNullVin = (vehicle: IVehicle): vehicle is IVehicleNonNullVin =>{
        return vehicle.vin !== null
    }
    
    if (!isNonNullVin(myVehicle)) {
        throw new Error('null');
    } else {
        needsVin(myVehicle);
    }
    

    如果原始类型兼容,TypeScript 会将变量缩小为特定类型。

    Demo in TS Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多