Не могу определить тип в TS - PullRequest
0 голосов
/ 09 июля 2020
interface Command {}

class RemoveCommand implements Command {}

class AddCommand implements Command {}

type Params = RemoveCommand | AddCommand; 

type Result<T> = 
  T extends RemoveCommand ? { status: string, a: number } :
  T extends AddCommand ? { status: string, b: number }:
  { status: string }

function send<T extends Command>(command: T): Result<T> {
  if (command instanceof RemoveCommand) {
    return { status: '', a: 0 } as Result<T>
  } else if (command instanceof AddCommand) {
    return {
      status: '',
      b: 0,
    } as Result<T>
  }

  return {
    status: '',
  } as Result<T>
}
const r1: { b: number } = send(new RemoveCommand());

Показать ошибку:

Свойство 'b' отсутствует в типе '{status: string; число; } 'но требуется в типе' {b: number; } '. (2741) Что я сделал не так?

1 Ответ

0 голосов
/ 09 июля 2020

Есть несколько проблем.

Во-первых, вы перепутали a и b:

type Result<T> = 
    T extends RemoveCommand ? { status: string, a: number } :
    T extends AddCommand ? { status: string, b: number }:
    { status: string };

Говорит, что send(new RemoveCommand()) вернет член, который имеет a не будет, поэтому ваша последняя строка неверна. Однако, когда вы исправите это, вы все равно получите ошибку.

Проблема root в том, что RemoveCommand и AddCommand одинаковы (оба являются пустыми классами). Вы можете увидеть, что, попробовав let foo: RemoveCommand = new AddCommand(), TypeScript тоже примет это.

После того, как вы определите (разные) члены в RemoveCommand и AddCommand, ваш код будет работать. Например:

interface Command {}

class RemoveCommand implements Command {
  thingToRemove: string;

  constructor(thing: string) {
    this.thingToRemove = thing;
  }
}

class AddCommand implements Command {
  thingToAdd: string;

  constructor(thing: string) {
    this.thingToAdd = thing;
  }
}

type Params = RemoveCommand | AddCommand; 

type Result<T> = 
    T extends RemoveCommand ? { status: string, a: number } :
    T extends AddCommand ? { status: string, b: number }:
    { status: string }

function send<T extends Command>(command: T): Result<T> {
  if (command instanceof RemoveCommand) {
    return { status: '', a: 0 } as Result<T>;
  } else if (command instanceof AddCommand) {
    return {
      status: '',
      b: 0,
    } as Result<T>
  }

  return {
    status: '',
  } as Result<T>
}

const r1: { a: number } = send(new RemoveCommand("foo"));
const r2: { b: number } = send(new AddCommand("bar"));
...