打字稿通过兄弟属性推断类型

时间:2021-03-20 14:42:49

标签: typescript

我正在尝试用打字稿制作一个框架。
我需要一个编译时数据检查。

我的打字稿界面代码

type TypeInfo = 'string' | 'number' | 'boolean';

type GetType<T extends TypeInfo> = T extends 'string'
  ? string
  : T extends 'number'
  ? number
  : T extends 'boolean'
  ? boolean
  : never;

interface StateInfo {
  // TypeInfo
  type: TypeInfo;
  default: GetType<this['type']>;
}

预期(编译时间)

// OK
const test1: StateInfo = {
  type: 'number',
  default: 1,
};

// Bad ('default' property is not number or 'type' property is not 'string') 
const test2: StateInfo = {
  type: 'number',
  default: 'test',
};

但是,打字稿编译代码没有任何错误。
如何正确声明 'default' 属性的类型?

2 个答案:

答案 0 :(得分:1)

问题

GetType<this['type']> 在声明 StateInfo 期间被评估。我的意思是,default 的类型将是 string | number | boolean,并且在创建对象时不会受到属性 type 的值的影响。

解决方案

使用Discriminated Unions

type StateInfoString = {
  type: 'string'
  default: string
}

type StateInfoNumber = {
  type: 'number'
  default: number
}

type StateInfoBoolean = {
  type: 'boolean'
  default: boolean
}

type StateInfo = StateInfoString | StateInfoNumber | StateInfoBoolean

// OK
const test1: StateInfo = {
  type: 'number',
  default: 1,
};

// error
const test2: StateInfo = {
  type: 'number',
  default: 'test',
};

Playground

答案 1 :(得分:1)

@Shivam Singla 的回答是完全有效的,我相信应该被接受。请将我的回答视为附加内容)

如果你想推断,我相信最好的方法是将函数与泛型结合使用:

type TypeInfo = 'string' | 'number' | 'boolean';

type GetType<T extends TypeInfo> = T extends 'string'
    ? string
    : T extends 'number'
    ? number
    : T extends 'boolean'
    ? boolean
    : never;

interface StateInfo {
    // TypeInfo
    type: TypeInfo;
    default: GetType<this['type']>;
}

const test = <T extends TypeInfo>(arg: T, prop: GetType<T>): StateInfo => {
// this return valu is just a mock, you should provide here your valid code
    return null as any
}

const result = test('string','str') // ok
const result2 = test('number',1) // ok
const result3 = test('boolean', true) // ok

const result4 = test('boolean', 1) // expected error
const result5 = test('string', false) // expected error

现在,您的 StateInfo 正在做您想做的事。