Условные типы Typescript и свойства объекта - PullRequest
1 голос
/ 06 июня 2019

Можно ли объявить универсальный класс (или фабричную функцию, как в примере) в TypeScript, который принимает двоичную переменную условного типа, которая влияет на тип свойства класса и связанные функции?

Например:

export function CreateModel<T extends 'CREATE' | 'UPDATE'>(mode: T) {
  type valueType = T extends 'CREATE' ? { name: string } : { name: string; email: string };
  return {
    value: {} as valueType,
    onChange(change: Partial<valueType>) {
      if (mode === 'UPDATE') {
        this.value.email = change.email;
      }
    }
  };
} 

1 Ответ

0 голосов
/ 06 июня 2019

Похоже, вы расширяете строку с помощью T extends 'CREATE' | 'UPDATE', я не уверен, что вы можете это сделать. Это в основном говорит «это может быть любая строка или эти две конкретные строки» - и это по сути то же самое, что сказать «любая строка»

Если вы хотите сказать, что хотите, чтобы входное значение было 'CREATE' или 'UPDATE', то вы можете разрешить только эти две строки, выполнив CreateModel(mode: 'CREATE' | 'UPDATE')

Другая проблема заключается в том, что вы используете this, но вы находитесь внутри функции, а не класса, поэтому она работает не совсем так, и у вас могут возникнуть некоторые проблемы, независимо от этого. как правило, это не рекомендуется, и вы должны использовать класс.

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

type ICreateType = { name: string };
type IUpdateType = { name: string; email: string | undefined };
interface IReturnCreateValue {
  value: ICreateType,
};
interface IReturnUpdateValue {
  value: IUpdateType,
  onChange: (change: Partial<IUpdateType>) => void;
};

export function CreateModel(mode: 'CREATE' | 'UPDATE'): IReturnCreateValue | IReturnUpdateValue { 
  if (mode === 'CREATE') {
    return { value: { name: '' } };
  }

  let value: IUpdateType = { name: '', email: '' };
  return {
    value: value,
    onChange(change: Partial<IUpdateType>) {
      value.email = change.email;
    }
  };
};

CreateModel('CREATE');
CreateModel('UPDATE');
CreateModel('foo'); //compile error

Вот идея, как это может работать в классе (также на площадке для машинописи )

type IValueType = { name: string; email?: string };
interface IValue {
  value: IValueType,
  onChange?: (change: Partial<IValueType>) => void;
};

class CreateModel {
  value: IValueType = { name: '' };
  onChange: undefined | ((c: Partial<IValueType>) => void) = undefined;

  constructor(private readonly shouldUpdate: boolean) {
    if (this.shouldUpdate) {
      this.onChange = (change: Partial<IValueType>) {
        this.value.email = change.email;
      }
    }
  }
}

const a = new CreateModel(false);
const b = new CreateModel(true);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...