首页 > 解决方案 > Typescript 中的强类型转换

问题描述

如果转换为接口的对象类型没有接口定义的原型/结构,有什么方法会出错?

interface IUser {
 id : string,
 name : string,
 address : string
}

仅填充 IUser 的几个属性

let data : any = {}; //let data : IUser = <IUser>{}; 
data.id = "123";
data.name = "name";

期待下面的编译时错误。

const user : IUser = <IUser>data; //<= Any way to get an error here saying address property doesn't exist at compile time?

更新:添加存在此类要求的上下文。

考虑 IUser 接口有许多属性,并且不想在构造它时错过分配任何属性。在这种情况下,只有编译错误会更有帮助。这主要是为了在 DDD 设计中传递 DTO 对象。这些通常带有许多参数。

标签: typescript

解决方案


这得看情况。

对于初学者:TypeScript 编译器,作为一个编译器,不能在运行时检查接口。它可以检查您在代码中的类型。

因此,如果您只有一些来自外部源的随机数据,TypeScript 编译器在运行时无法为您做任何事情:您的有问题的数据是在编译器执行任务之后很久才构建的。为此,您需要一些运行时检查系统,例如io-ts

如果您的需求更有限,您可以编写一个自定义类型保护。像(前面未经测试的代码):

function isIUser(obj: any): obj is IUser {
    return obj && typeof obj.id === 'string' && typeof obj.name === 'string' && typeof obj.address === 'string';
}

let data : any = {}; //let data : IUser = <IUser>{}; 
data.id = "123";
data.name = "name";
if (isIUser(data)) {
  // inside this block data is of type IUser
} else {
  // error
}

第二:TypeScript 转换并没有真正执行任何操作或检查。这是一种告诉 TS 编译器“相信我,我比你更清楚,这真的是一个IUser”的方式。
而且,作为一个听话的软件,编译器相信你传递的任何东西:好数据,坏数据,字符串,数字,未定义,你说的。所以,把你的演员限制在最低限度。

如果您允许他执行其工作,编译器将为您彻底执行检查:

// Do NOT use any as a type. Tell the compiler what he should enforce
const data : IUser = {
  id: "123",
  name: "name"
}; // --> compile time error.

编辑:

如果您需要调用过程或其他,您只需使用支持变量:

// telling the compiler the result must honor the IUser interface
mapIUserDto(userInputs: Something): IUser {
  const name = this.normalizeName(userInputs.name),
        address = this.mapAddress(userInputs);

  // using object composition you colud skip even property names
  // if a property is missing, you'll get a nice error message. 
  return {
    id: userInputs.id,
    name: name,
    address: address
  };
}

推荐阅读