Применение определенного значения с использованием определения типа Typescript - PullRequest
0 голосов
/ 17 марта 2019

У меня есть класс Car, который определяет свойство для model автомобиля.

Возможны только 3 модели: «ModelT», «ModelQ» и «ModelX». Поэтому я решил определить тип модели, например:

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

и метод конструктора Car как

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

Существует также удаленная служба, которая возвращает тип автомобиля, который я должен купить. Если я использую такой сервис, мой код выглядит как

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

Какой лучший способ применить логику для проверки во время выполнения , что модель, возвращаемая удаленной службой, на самом деле является одной из тех, которые указаны в определении type Model?

1 Ответ

1 голос
/ 17 марта 2019

Невозможно начать с типа / интерфейса и получить от него поведение во время выполнения.Система типов в TypeScript существует только в то время, когда вы пишете программу. полностью стерто из испущенного JavaScript, который выполняется во время выполнения.

К счастью, вы можете сделать наоборот: начать с объекта, который существует во время выполнения, и получитькомпилятор 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, которое вы можете использовать для создания для него охранника типа :

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

Хорошо, надеюсь, это поможет.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...