网站搜索

typescript - 将现有类型转换为具有一个属性更改的新类型


如何将现有类型转换为具有一个属性更改的新类型?

TypeScript 沙盒

示例:

type SomeComplexType = string // just for example

// cannot be changed
type Options<T> = {
    opt1: boolean | undefined;
    opt2: number;
    opt3?: SomeComplexType;
    opt4: T
}

// Can be changed

// How to change opt1 to accept only true and infer other option types?
type Keys = keyof Options<any>

let r: { [K in Keys]: K extends 'opt1' ? true : any }

// Good (should work)
r = { opt1: true, opt2: 2, opt3: '1', opt4: 1 }
r = { opt1: true, opt2: 2, opt3: '1', opt4: 'str' }

// Bad (should be error)
r = { opt1: false, opt2: 1, opt3: 'str', opt4: 1 } // opt1 should be true
r = { opt1: true, opt2: 'str', opt3: 'str', opt4: 1 } // opt2 should be number
r = { opt1: true, opt2: 'str', opt3: 1, opt4: 1 } // opt3 should be 

答案#1

如果你有一个对象类型 O,并且想要创建一个新类型,使得所有属性键和值都相同,只是键为 opt1 的属性应该是 true,你可以这样写:

{ [K in keyof O]: K extends 'opt1' ? true : O[K] }

语法 O[K] 是一种索引访问,意思是“键类型为 K 的 O 属性的类型”。

那么你的示例应该会按预期工作,(假设 O 是 Options<any>):

// Good 
r = { opt1: true, opt2: 2, opt3: '1', opt4: 1 } // okay
r = { opt1: true, opt2: 2, opt3: '1', opt4: 'str' } // okay

// Bad 
r = { opt1: false, opt2: 1, opt3: 'str', opt4: 1 } // error!
r = { opt1: true, opt2: 'str', opt3: 'str', opt4: 1 } // error!
r = { opt1: true, opt2: 'str', opt3: 1, opt4: 1 } // error!

代码的 Playground 链接