打字稿条件类型和对象属性

时间:2019-06-06 18:37:40

标签: typescript conditional-types

是否可以在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 :(得分:0)

因此,看起来您正在使用T extends 'CREATE' | 'UPDATE'扩展字符串,我不确定您可以这样做。基本上是说“可以是任何字符串,也可以是这两个特定的字符串”-基本上与说“任何字符串”相同

如果您要说只希望输入值是'CREATE''UPDATE',则只能通过输入来允许这两个字符串 CreateModel(mode: 'CREATE' | 'UPDATE')

另一个问题是您正在使用this,但您位于函数而不是类的内部,因此它的工作方式并不完全相同,并且您可能会遇到一些问题。通常不建议这样做,您应该使用一个类。

这就是我想出的,and it compiles。我知道它首先可以解决您最初提出的问题,但是我相信那也是因为您不在这里使用课程

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

这里是关于如何将其作为类工作的想法(也on typescript playground

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);