Bei der Transformation von Arrays mit map werden häufig nur bestimmte Eigenschaften benötigt, nicht das gesamte Objekt. Inline-Schreibweise kann ausführlich sein, aber durch die vorherige Definition einer Property-Extractor-Funktion sind prägnante Ausdrücke wie map(propsExtractor('id', 'name')) möglich.
Code
type LiteralObject = Record<string, unknown>
/** * Generiert eine Funktion, die nur angegebene Eigenschaften aus einem Objekt extrahiert */export function propsExtractor< Props extends LiteralObject, PropKey extends keyof Props,>( ...props: PropKey[]): (obj: Props) => Pick<Props, PropKey> { return (obj: Props) => { const result: Partial<Props> = {} for (const prop of props) { if (Object.hasOwn(obj, prop)) { result[prop] = obj[prop] } } return result as Pick<Props, PropKey> }}Verwendung
type User = { id: string name: string email: string role: string createdAt: Date}
const users: User[] = [ { id: '1', name: 'Alice', email: 'alice@example.com', role: 'admin', createdAt: new Date() }, { id: '2', name: 'Bob', email: 'bob@example.com', role: 'user', createdAt: new Date() },]
// Nur ID und Name extrahierenconst userSummaries = users.map(propsExtractor('id', 'name'))// => [{ id: '1', name: 'Alice' }, { id: '2', name: 'Bob' }]
// Funktioniert sauber auch in verschachtelten Mapsconst departments = [ { name: 'Engineering', members: users }, { name: 'Sales', members: users },]
const summaries = departments.map(dept => ({ department: dept.name, members: dept.members.map(propsExtractor('id', 'name'))}))Funktionsweise
propsExtractorakzeptiert zu extrahierende Property-Namen als variable Argumente- Gibt eine Funktion vom Typ
(obj: Props) => Pick<Props, PropKey>als Closure zurück - Die zurückgegebene Funktion prüft die Existenz der Eigenschaft mit
Object.hasOwnvor der Extraktion - TypeScripts
Pick-Utility-Typ gewährleistet genaue Typinferenz für den Rückgabewert
Die Verwendung von Object.hasOwn gewährleistet Sicherheit, indem Eigenschaften aus der Prototypenkette nicht versehentlich extrahiert werden.
Vorteile
- Lesbar: Absicht ist klar mit Ausdrücken wie
map(propsExtractor('id', 'name')) - Typsicher: TypeScript-Typinferenz bestimmt den extrahierten Typ genau
- Wiederverwendbar: Einmal definieren, an mehreren Stellen verwenden
- Handhabt Verschachtelung gut: Bewahrt Lesbarkeit auch bei mehreren
mapBy-Anwendungen
Vorsichtsmaßnahmen
Eigenschaften, die nicht existieren, sind nicht im Ergebnis enthalten (auch nicht als undefined). Wenn Sie alle Eigenschaften einschließen möchten, entfernen Sie die Object.hasOwn-Prüfung. Wenn Sie viele Eigenschaften extrahieren, kann es wartbarer sein, explizit ein Interface zu definieren.
Anwendungen
- Nur notwendige Felder aus API-Antworten extrahieren, bevor sie an Clients zurückgegeben werden
- Eigenschaften mit sensiblen Informationen beim Logging ausschließen (inverse Filterversion erstellen)
- Teilzustand in Redux- oder Zustand-Selektoren extrahieren
- Teilabruflogik ähnlich der GraphQL-Feldauswahl implementieren
hsb.horse