Próbuję użyć następującego wzoru:
enum Option {
ONE = 'one',
TWO = 'two',
THREE = 'three'
}
interface OptionRequirement {
someBool: boolean;
someString: string;
}
interface OptionRequirements {
[key: Option]: OptionRequirement;
}
Wydaje mi się to bardzo proste, jednak pojawia się następujący błąd:
Typ parametru podpisu indeksu nie może być typem unii. Zamiast tego rozważ użycie mapowanego typu obiektu.
Co ja robię źle?
javascript
typescript
john maccarthy
źródło
źródło
key
może być tylko ciągiem znaków, liczbą lub symbolem. enum nie jest.Odpowiedzi:
Możesz użyć operatora TS „in” i zrobić to:
enum Options { ONE = 'one', TWO = 'two', THREE = 'three', } interface OptionRequirement { someBool: boolean; someString: string; } type OptionRequirements = { [key in Options]: OptionRequirement; // Note that "key in". }
źródło
interface OptionRequirements
natype OptionRequirements
Najprostszym rozwiązaniem jest użycie
Record
Możesz również zaimplementować to samodzielnie jako:
type OptionRequirements = { [key in Options]: OptionRequirement; }
Ta konstrukcja jest dostępna tylko dla
type
, ale nieinterface
.Problem w twojej definicji polega na tym, że klucz twojego interfejsu powinien być typu
Options
, gdzieOptions
jest wyliczeniem, a nie ciągiem, liczbą lub symbolem.Te
key in Options
środki „dla tych konkretnych klawiszy, które w Opcjach Union Typ”.type
alias jest bardziej elastyczny i potężniejszy niżinterface
.Jeśli Twój typ nie musi być używany na zajęciach, wybierz
type
innyinterface
.źródło
Miałem podobny problem, ale mój przypadek dotyczył innej właściwości pola w interfejsie, więc moje rozwiązanie jako przykład z opcjonalną właściwością pola z wyliczeniem dla kluczy:
export enum ACTION_INSTANCE_KEY { cat = 'cat', dog = 'dog', cow = 'cow', book = 'book' } type ActionInstances = { [key in ACTION_INSTANCE_KEY]?: number; // cat id/dog id/cow id/ etc // <== optional }; export interface EventAnalyticsAction extends ActionInstances { // <== need to be extended marker: EVENT_ANALYTIC_ACTION_TYPE; // <== if you wanna add another field to interface }
źródło
Zamiast używać interfejsu, użyj odwzorowanego typu obiektu
enum Option { ONE = 'one', TWO = 'two', THREE = 'three' } type OptionKeys = keyof typeof Option; interface OptionRequirement { someBool: boolean; someString: string; } type OptionRequirements = { // note type, not interface [key in OptionKeys]: OptionRequirement; // key in }
źródło
W moim przypadku potrzebowałem, aby właściwości były opcjonalne, więc utworzyłem ten typ ogólny.
type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T; };
Następnie użyj go jako takiego:
type MyTypes = 'TYPE_A' | 'TYPE_B' | 'TYPE_C'; interface IContent { name: string; age: number; } interface IExample { type: string; partials: PartialRecord<MyTypes, IContent>; }
Przykład
const example : IExample = { type: 'some-type', partials: { TYPE_A : { name: 'name', age: 30 }, TYPE_C : { name: 'another name', age: 50 } } }
źródło
Miałem podobny problem. Próbowałem używać tylko określonych kluczy podczas tworzenia walidatorów kątowych.
export enum FormErrorEnum { unknown = 'unknown', customError = 'customError', } export type FormError = keyof typeof FormErrorEnum;
I użycie:
static customFunction(param: number, param2: string): ValidatorFn { return (control: AbstractControl): { [key: FormErrorEnum]?: any } => { return { customError: {param, param2} }; }; }
Pozwoli to na użycie 1 - X liczby kluczy.
źródło