使用 Typescript 的类型定义强制执行某个值

Enforcing a certain value using Type definition of Typescript

我有一个Carclass,它为车的model定义了属性

只有 3 种可能的模型:'ModelT'、'ModelQ' 和 'ModelX'。所以我决定定义一个模型类型,例如:

type Model = 'ModelT' | 'ModelQ' | 'ModelX';

Car 构造方法为

class Car {
  constructor(model: Model) {
    this.model = model;
  }
}

还有一个远程服务returns我应该买什么车。如果我使用这样的服务,我的代码看起来像

const model = getModelFromRemoteService();
const car = new Car(model);

执行逻辑以检查 在运行时 远程服务返回的模型实际上是 type Model 定义中指定的模型之一的最佳方式?

无法从 type/interface 开始并从中获取运行时行为。 TypeScript 中的类型系统仅在您编写程序时存在。它是在运行时执行的发出的 JavaScript 中的 completely erased

幸运的是,您可以做相反的事情:从运行时存在的对象开始,让 TypeScript 编译器为它推断一个类似的类型。在你的情况下,我建议从你要检查的值数组开始,然后按照 :

所述进行
// helper function needed before TS3.4 to get a tuple of string literals
// instead of just string[]
const stringTuple = <T extends string[]>(...args: T) => args;

const models = stringTuple('ModelT', 'ModelQ', 'ModelX');
// inferred type of models is ['ModelT', 'ModelQ', 'ModelX'];

// in TS3.4+, const models = ['ModelT', 'ModelQ', 'ModelX'] as const;

type Model = typeof models[number];
// inferred type of Model is 'ModelT' | 'ModelQ' | 'ModelX'

现在您的 Model 类型又回来了,您还有 models 数组值,可用于为其创建 type guard

function isModel(x: any): x is Model {
  return models.indexOf(x) >= 0;
  // or return models.includes(x) for ES2016+
}

现在您可以像这样使用它了:

class Car {
  model: Model;
  constructor(model: Model) {
    this.model = model;
  }
}
// assume this returns a string
declare function getModelFromRemoteService(): string;

// wrap getModelFromRemoteService so that it returns a Model 
// or throws a runtime error
function ensureModelFromRemoteService(): Model {
  const model = getModelFromRemoteService();
  if (isModel(model)) return model;
  throw new Error("THAT REMOTE SERVICE LIED TO ME");
}


const model = ensureModelFromRemoteService();
const car = new Car(model); // works now

好的,希望对您有所帮助。祝你好运!