Bir dizin imzası parametre türü bir birleşim türü olamaz. Bunun yerine eşlenmiş bir nesne türü kullanmayı düşünün


104

Aşağıdaki kalıbı kullanmaya çalışıyorum:

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

interface OptionRequirements {
  [key: Option]: OptionRequirement;
}

Bu bana çok basit görünüyor, ancak şu hatayı alıyorum:

Bir dizin imzası parametre türü bir birleşim türü olamaz. Bunun yerine eşlenmiş bir nesne türü kullanmayı düşünün.

Neyi yanlış yapıyorum?


1
Tür keyyalnızca dizi, sayı veya simge olabilir. enum değil.
2019

Yanıtlar:


160

TS "in" operatörünü kullanabilir ve bunu yapabilirsiniz:

enum Options {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three',
}
interface OptionRequirement {
  someBool: boolean;
  someString: string;
}
type OptionRequirements = {
  [key in Options]: OptionRequirement; // Note that "key in".
}

5
Eee, bu derlenmiyor mu? Typescript oyun alanı diyor : "Bir arabirimde bir bilgisayarlı özellik adı ile tipi değişmez türü veya bir 'benzersiz sembolü' türü bir ifadesi başvurması gerekir."
meriton

19
Değişim interface OptionRequirementsiçintype OptionRequirements
Tyler Rick

3
bu aslında benim için işe yaramıyor: Bir arayüzdeki hesaplanan bir özellik adı, türü değişmez tür veya 'benzersiz sembol' türü olan bir ifadeye başvurmalıdır
Tyguy7

Typecript'in hangi sürümünü kullandığınızı bize söyler misiniz?
Nacho Justicia Ramos

2
Arayüz yerine eşlenmiş bir tür takma adı kullanmak için bu yanıtı düzenledim. Orijinal yanıt, gördüğüm herhangi bir TypeScript sürümü altında derlenmiyor ve kesinlikle TypeScript'in mevcut sürümü (Ağustos 2020 itibariyle 4.0) altında derlenmiyor. @NachoJusticiaRamos, eğer orijinal sürümünüzün bir TypeScript sürümünde gerçekten bir yerde çalıştığını gösterebilseydiniz, o zaman düzenlemeyi ve çalışması için kullanmanız gereken ortamın bir açıklamasını geri döndürmekten memnuniyet duyarım. Şerefe!
jcalz

58

En basit çözüm kullanmaktır Record

type OptionRequirements = Record<Options, OptionRequirement>

Kendiniz de şu şekilde uygulayabilirsiniz:

type OptionRequirements = {
  [key in Options]: OptionRequirement;
}

Bu yapı yalnızca kullanılabilir type, ancak değil interface.

Tanımınızdaki problem, arayüzünüzün anahtarının bir dizge, sayı veya sembol değil, bir enum Optionsolduğu türde olması gerektiğini söylemektir Options.

key in Options"Sendika tipi Seçenekleri var bu özel tuşlar için" anlamına gelir.

typealias daha esnek ve güçlüdür interface.

Senin tipin sınıfında kullanılmak üzere ihtiyaç yoksa, seçim typeüzerinde interface.


5

Benzer bir sorun yaşadım ama benim durumum arayüzde başka bir alan özelliğindeydi, bu nedenle çözümüm, anahtarlar için bir numaralandırmalı isteğe bağlı alan özelliğine sahip bir örnek olarak :

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
}

4

Arayüz kullanmak yerine eşlenmiş bir nesne türü kullanın

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
}

1

Benim durumumda özelliklerin isteğe bağlı olmasına ihtiyacım vardı, bu yüzden bu genel türü yarattım.

type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T; };

O halde şu şekilde kullanın:

type MyTypes = 'TYPE_A' | 'TYPE_B' | 'TYPE_C';

interface IContent {
    name: string;
    age: number;
}

interface IExample {
    type: string;
    partials: PartialRecord<MyTypes, IContent>;
}

Misal

const example : IExample = {
    type: 'some-type',
    partials: {
        TYPE_A : {
            name: 'name',
            age: 30
        },
        TYPE_C : {
            name: 'another name',
            age: 50
        }
    }
}

0

Benzer bir sorun yaşadım. Açısal form doğrulayıcıları oluştururken yalnızca belirli anahtarları kullanmaya çalışıyordum.

export enum FormErrorEnum {
  unknown = 'unknown',
  customError = 'customError',
}

export type FormError = keyof typeof FormErrorEnum;

Ve kullanım:

static customFunction(param: number, param2: string): ValidatorFn {
  return (control: AbstractControl): { [key: FormErrorEnum]?: any } => {
    return { customError: {param, param2} };
  };
}

Bu, 1 - X sayıda anahtarın kullanılmasına izin verecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.