I have this function as below that works well:
function pickAttributes<K extends string, T> (e: Element, attrs: K[]): Record<K, string> {
return attrs.reduce((obj, key) => {
return {
...(obj as any),
[key]: e.getAttribute(key)
}
}, {})
}
I want to be able to have this function take an optional map function to convert the attributes to a different type.
function pickAttributes<K extends string, T> (e: Element, attrs: K[], mapFn?: (attr: null | string) => T): Record<K, T> {
if (!mapFn) mapFn = x => String(x)
return attrs.reduce((obj, key) => {
return {
...(obj as any),
[key]: mapFn(e.getAttribute(key))
}
}, {})
}
However i get this error
TS2322:
Type '(x: string | null) => string' is not assignable to type '((attr: string | null) => T) | undefined'.
Type '(x: string | null) => string' is not assignable to type '(attr: string | null) => T'.
Type 'string' is not assignable to type 'T'.
I get a similar error if i try to use a default parameter.
The changed function seems to work as expected without trying to add a default
function pickAttributes<K extends string, T> (e: Element, attrs: K[], mapFn?: (attr: null | string) => T): Record<K, T> {
return attrs.reduce((obj, key) => {
return {
...(obj as any),
[key]: e.getAttribute(key)
}
}, {})
}
First: I'm not sure what could extend string, so I would drop the generic parameter K.
But anyway: you want your return type to vary, based on the presence of the mapFn argument. I would solve that by defining two overloads of the function. And in the implementation, by using a union type string | T
string | T
:
function pickAttributes<K extends string>(e: Element, attrs: K[]): Record<K, string>;
function pickAttributes<K extends string, T> (e: Element, attrs: K[], mapFn: (attr: null | string) => T): Record<K, T>;
function pickAttributes<K extends string, T> (e: Element, attrs: K[], mapFn?: (attr: null | string) => T): Record<K, string | T> {
const fn = mapFn || (x => String(x));
return attrs.reduce((obj, key) => {
return {
...(obj as any),
[key]: fn(e.getAttribute(key))
}
}, {});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.