[英]Return object from function with keys based on a property of the input object in Typescript
I'm trying to create a function that receives an object with certain properties, then use one of those properties in order to generate the types of the result.我正在尝试创建一个接收具有某些属性的 object 的 function,然后使用其中一个属性来生成结果的类型。
function params function 参数
interface Params<T> {
entries?: { [key in T['entries']: string]: number }
unit?: string
}
and the result和结果
type Result<T> = { [key in T: string]: string }
where T in the result is Params['entries']
结果中的 T 是Params['entries']
I setup a simple typescript playground to display my attempt.我设置了一个简单的typescript 操场来展示我的尝试。
At the moment, if you type result.
目前,如果您键入result.
it only suggests big|small
which are the default values, and not a
which was the actual object input.它只建议big|small
是默认值,而不是实际a
object 输入。
The problem lies here问题出在这里
generateUnitStrings = <O>(options?: Params<O>) // ---> the <O>
What is O?什么是O? That's why PickEntries<O> extends never
returns true.这就是为什么PickEntries<O> extends never
返回 true 的原因。 One way to check is doing this一种检查方法是这样做
const result = generateUnitStrings<{ entries: { a: number } }>({ entries: { a: 1 } })
And you'll see that it actually works.你会发现它确实有效。 autocompletion correctly suggests 'a'.自动完成正确地提示“a”。 The reason is when you call generateUnitStrings
, O
correctly gets switched with { entries: { a: number } }
and passes it to Params and everything works.原因是当您调用generateUnitStrings
时, O
正确地切换为{ entries: { a: number } }
并将其传递给 Params 并且一切正常。
Try this (it looks a little bit weird to me, but it actually works:):试试这个(对我来说看起来有点奇怪,但它确实有效:):
export const generateUnitStrings = <O extends Params<O>>(options?: O) => {
...
EDIT编辑
Yes, but now your solution only suggests something if generateUnitStrings() has parameters, if it used empty as generateUnitStrings() it doesn't auto-suggests the default parameters small|big是的,但是现在您的解决方案仅在 generateUnitStrings() 具有参数时提出建议,如果它使用空作为 generateUnitStrings() 它不会自动建议默认参数 small|big
Providing a default generic type (in this case typeof defaultParams) seems to get the job done提供默认的泛型类型(在本例中为 typeof defaultParams)似乎可以完成工作
export const generateUnitStrings = <O extends Params<O> = typeof defaultParams>(options?: O) => {
const entries = (options && options.entries) || defaultParams.entries
const unit = (options && options.unit) || defaultParams.unit
return Object.keys(entries).reduce(
(acc, v) => ({ ...acc, [v]: `${entries[v as keyof typeof entries]}${unit}` }),
{}
) as PickEntries<O> extends never ? Result<PickEntries<typeof defaultParams>> : Result<PickEntries<O>>
}
Your initial code for reference您的初始代码供参考
type FilterProperties<T, P> = {
[K in keyof T]: K extends P ? K : never
}[keyof T]
type PickEntries<T> = T[FilterProperties<T, 'entries'>]
interface Params<T> {
entries?: { [K in keyof PickEntries<T>]: number }
unit?: string
}
type Result<T> = { [P in keyof T]: string }
export const defaultParams = {
entries: {
small: 600,
big: 1200,
},
unit: 'px',
}
export const generateUnitStrings = <O>(options?: Params<O>) => {
const entries = (options && options.entries) || defaultParams.entries
const unit = (options && options.unit) || defaultParams.unit
return Object.keys(entries).reduce(
(acc, v) => ({ ...acc, [v]: `${entries[v as keyof typeof entries]}${unit}` }),
{}
) as PickEntries<O> extends never ? Result<PickEntries<typeof defaultParams>> : Result<PickEntries<O>>
}
const result = generateUnitStrings({ entries: { a: 1 } })
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.