Typescript:基于兄弟对象键的值的强类型(和自动完成)
Typescript: Strong-typing (and autocomplete) for a value based on a sibling object's keys
假设我有一个看起来像这样的对象:
const configuration: Config = {
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOption: 'Option 1'
}
如何编写类型 Config
使得:
defaultOption
只能是 .options
对象中的键之一。 IE。 'Option 1'
或 'Option 2'
在上面的例子中。
.options
可以有任意数量的键值对。
- 用户不必预先指定
.options
键。因此,用户不必指定 const configuration: Config<'Option 1' | 'Option 2'> = ...
。可以使用泛型,但用户不必指定它们。
为了做到这一点并进行验证,您需要从函数参数推断您的配置对象:
type Configuration<
Options
>
= {
options: Options,
defaultOption: keyof Options
}
const config = <
Options extends Record<string, string>,
Config extends Configuration<Options>,
Default extends keyof Config['options'],
>(config: { options: Options, defaultOptions: Default }) => config
const result = config({
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOptions: 'Option 1'
}) // ok
const result2 = config({
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOptions: 'invalid property'
}) // error
假设我有一个看起来像这样的对象:
const configuration: Config = {
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOption: 'Option 1'
}
如何编写类型 Config
使得:
defaultOption
只能是.options
对象中的键之一。 IE。'Option 1'
或'Option 2'
在上面的例子中。.options
可以有任意数量的键值对。- 用户不必预先指定
.options
键。因此,用户不必指定const configuration: Config<'Option 1' | 'Option 2'> = ...
。可以使用泛型,但用户不必指定它们。
为了做到这一点并进行验证,您需要从函数参数推断您的配置对象:
type Configuration<
Options
>
= {
options: Options,
defaultOption: keyof Options
}
const config = <
Options extends Record<string, string>,
Config extends Configuration<Options>,
Default extends keyof Config['options'],
>(config: { options: Options, defaultOptions: Default }) => config
const result = config({
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOptions: 'Option 1'
}) // ok
const result2 = config({
options: {
'Option 1': 'some value here',
'Option 2': 'some other value here'
},
defaultOptions: 'invalid property'
}) // error