Приведение объекта к интерфейсу в TypeScript

Я пытаюсь сделать приведение в моем коде из тела запроса в express (используя промежуточное ПО body-parser) к интерфейсу, но он не работает. Это возможно сделать?

Это мой интерфейс:

export interface IToDoDto {
  description: string;
  status: boolean;
};

Это код, где я пытаюсь сделать бросок:

@Post()
addToDo(@Response() res, @Request() req) {
  const toDo: IToDoDto = <IToDoDto> req.body;
  this.toDoService.addToDo(toDo);
  return res.status(HttpStatus.CREATED).end();
}

и, наконец, метод службы, который называется:

public addToDo(toDo: IToDoDto): void {
  toDo.id = this.idCounter;
  this.todos.push(toDo);
  this.idCounter++;
}

Я могу передать все аргументы и это будет работать нормально. Я прочитал это в TypeScript не существует приведения, но утверждение типа, поэтому он будет только сообщать компилятору, что объект имеет тип x, поэтому... Я ошибаюсь? И как это сделать? Спасибо.

2 ответов


в javascript нет кастинга, поэтому вы не можете бросить, если "кастинг не удается".
Typescript поддерживает литье но это только на время компиляции, и вы можете сделать это так:

const toDo = <IToDoDto> req.body;
// or
const toDo = req.body as IToDoDto;

Вы можете проверить во время выполнения, если значение является допустимым, а если не выдаст ошибку, т. е.:

function isToDoDto(obj: any): obj is IToDoDto {
    return typeof obj.description === "string" && typeof obj.status === "boolean";
}

@Post()
addToDo(@Response() res, @Request() req) {
    if (!isToDoDto(req.body)) {
        throw new Error("invalid request");
    }

    const toDo = req.body as IToDoDto;
    this.toDoService.addToDo(toDo);
    return res.status(HttpStatus.CREATED).end();
}

вот еще один способ заставить тип-cast даже между несовместимыми типами и интерфейсами, где компилятор TS обычно жалуется:

export function forceCast<T>(input: any): T {

  // ... do runtime checks here

  // @ts-ignore <-- forces TS compiler to compile this as-is
  return input;
}

затем вы можете использовать его для принудительного приведения объектов к определенному типу:

import { forceCast } from './forceCast';

const randomObject: any = {};
const typedObject = forceCast<IToDoDto>(randomObject);

обратите внимание, что я опустил часть, которую вы должны выполнить проверки времени выполнения перед кастингом ради снижения сложности. То, что я делаю в своем проекте, - это компиляция всех моих .d.ts файлы интерфейса в схемы JSON и использование ajv чтобы проверить в во время выполнения.