typescript - Einen optionalen, generischen Wert aus einem Objekt abrufen
Sagen wir, ich habe die folgenden vier Objekte:
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{foo2: number, bar2: ?string}> = {
foo2: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo2: 123,
bar2: '1123'
}
Ich möchte sie jetzt in fp-ts Option-tragende Objekte der Form umwandeln:
{foo: number, bar: Option<string>}
Der naive Ansatz besteht darin, zwei Funktionen zu schreiben (oder diese Berechnungen tatsächlich inline durchzuführen):
const makeOptional1 = (obj: Readonly<{foo: number, bar: ?string}>) => {
return (obj.bar === undefined) ? none : some(obj[key]
}
const makeOptional2 = (obj: Readonly<{foo2: number, bar2: ?string}>) => {
return (obj.bar2 === undefined) ? none : some(obj[key]
}
Aber sagen wir, dass ich eine stärker abstrahierte Funktion extrahieren wollte, eine, die ein beliebiges Objekt und einen beliebigen Schlüssel nehmen und die korrekte Option zurückgeben könnte.
Ein erster Versuch könnte ungefähr so aussehen:
const optionalKey = <T, D>(val: D, key: string): Option<T> => {
if (val[key] === undefined) {
return none
} else {
return some(val[key])
}
}
Dies kann nicht kompiliert werden mit:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053)
Die Fehlermeldung ergibt vollkommen Sinn, aber ich weiß nicht, wie ich sie beheben kann. Jede Idee wäre willkommen.
Antwort #1
bitte schau es dir an: TS-Spielplatz
import { Option, some, none } from 'fp-ts/lib/Option';
const foo1: Readonly<{ foo: number, bar?: string }> = {
foo: 123
}
const foo2: Readonly<{ foo: number, bar?: string }> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123
}
const bar2: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123,
bar2: '1123'
}
const makeOptional1 = <T extends Readonly<{ foo: number, bar?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar === undefined) ? none : some(obj[key])
}
const makeOptional2 = <T extends Readonly<{ foo2: number, bar2?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar2 === undefined) ? none : some(obj[key])
}
type Values<T> = T[keyof T];
const optionalKey = <T, K extends keyof T>(val: T, key: K): Option<Values<T>> => val[key] ? some(val[key]) : none;
const result = optionalKey({ age: 1 }, 'age'); // Option<number>
fp-ts Version: 2.8.6
