Hur man får egenskapsnamnet/nyckelnamnet för ett interface som en sträng i Typescript
Arbetar för närvarande med Slacks API och det finns fall där jag skickar JSON-förfrågningar med strängar, och dessa strängar returneras vid ett senare tillfälle som egenskapsnamn.
Jag skulle vilja ha ett gränssnitt och skicka ett av dess egenskapsnamn som en sträng. Och sedan ha det returnerade objektet korrekt typat. Jag vill inte behöva hantera "magiska strängar" eller konstanter som jag måste hålla synkroniserade med gränssnittet.
Snabbt exempel:
// This is the request I send out to Slack
const request = {
actionId: "specialProperty"
};
// And Slack might give me this object at a later point
const incomingWebhook = {
specialProperty: "Value I want to read"
}
Jag kan ganska lätt få in skrivande för detta med ett gränssnitt
interface SpecialPropertyInterface {
specialProperty: string;
}
Mitt problem är att detta gränssnitt är bundet till strängen som jag skickar ut.
Finns det ett sätt för mig att få nyckeln/egenskapen "specialProperty" från mitt SpecialPropertyInterface som en sträng?
Svar #1
Jag slutade med att lösa mitt problem genom att använda "keyof". Inte optimalt, men jag får en typesäker sträng som baseras på en egenskap i ett gränssnitt.
Jag hade två nästlade nycklar, så jag delade upp dem i två gränssnitt och använde keyof för att få strängen av egenskapen för var och en av dem.
export interface HoursBlock {
hours: HoursBlockAction;
}
export interface HoursBlockAction {
hoursAction: {
// eslint-disable-next-line camelcase
selected_option: {
value: string;
};
};
}
...
// This string will only be valid if you write the name of the property.
const hoursBlockId: keyof HoursBlock = "hours";
const hoursActionId: keyof HoursBlockAction = "hoursAction";
// If you type a different string you will trigger an error.
// Type '"wrong"' is not assignable to type '"hours"'.ts(2322)
const wrongHoursBlockId: keyof HoursBlock = "wrong";
Svar #2
Här är ett försök.
Först, lägg till as const som ett suffix till deklarationen av ditt request-objekt:
const request = {
actionId: "specialProperty"
} as const;
Som en följd är typen av egenskapen actionId ett literal ("specialProperty") istället för en string:
type RequestActionId = typeof request["actionId"] // "specialProperty"
Nu kan vi använda det i en mappad indexsignatur:
type SpecialPropertyInterface = {
[propName in RequestActionId]: string; // specialProperty: string
}
Lekplatslänk
