ชนิดพารามิเตอร์ลายเซ็นดัชนีไม่สามารถเป็นชนิดสหภาพได้ พิจารณาใช้ประเภทวัตถุที่แมปแทน


101

ฉันกำลังพยายามใช้รูปแบบต่อไปนี้:

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

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

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

ดูเหมือนจะตรงไปตรงมาสำหรับฉัน แต่ฉันได้รับข้อผิดพลาดต่อไปนี้:

ชนิดพารามิเตอร์ลายเซ็นดัชนีไม่สามารถเป็นชนิดสหภาพได้ พิจารณาใช้ประเภทวัตถุที่แมปแทน

ผมทำอะไรผิดหรือเปล่า?


1
ประเภทkeyสามารถเป็นสตริงตัวเลขหรือสัญลักษณ์เท่านั้น enum ไม่ใช่
unional

คำตอบ:


156

คุณสามารถใช้ตัวดำเนินการ TS "in" และทำสิ่งนี้:

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
เอิ่มนี่ไม่ได้คอมไพล์? typescript สนามเด็กเล่นกล่าวว่า : "ชื่อคุณสมบัติคำนวณในอินเตอร์เฟซจะต้องหมายถึงการแสดงออกที่มีชนิดเป็นชนิดตัวอักษรหรือสัญลักษณ์ที่ไม่ซ้ำกัน 'ชนิด."
ทำบุญ

19
เปลี่ยนinterface OptionRequirementsเป็นtype OptionRequirements
Tyler Rick

3
สิ่งนี้ใช้ไม่ได้สำหรับฉันจริง ๆ : ชื่อคุณสมบัติที่คำนวณในอินเทอร์เฟซต้องอ้างถึงนิพจน์ที่มีประเภทเป็นประเภทตัวอักษรหรือประเภท 'สัญลักษณ์เฉพาะ'
Tyguy7

คุณช่วยบอกเราได้ไหมว่าคุณใช้ typescript เวอร์ชันใดอยู่
Nacho Justicia Ramos

2
ฉันได้แก้ไขคำตอบนี้เพื่อใช้นามแฝงประเภทที่แมปแทนอินเทอร์เฟซ คำตอบเดิมไม่ได้รวบรวมภายใต้ TypeScript เวอร์ชันใด ๆ ที่ฉันเคยเห็นและแน่นอนว่าจะไม่รวบรวมภายใต้ TypeScript เวอร์ชันปัจจุบัน (4.0 ณ เดือนสิงหาคม 2020) @NachoJusticiaRamos หากคุณสามารถแสดงให้เห็นว่าเวอร์ชันดั้งเดิมของคุณใช้งานได้จริงในบางเวอร์ชันของ TypeScript ฉันยินดีที่จะยกเลิกการแก้ไขพร้อมกับคำอธิบายของสภาพแวดล้อมที่คุณต้องใช้เพื่อให้สามารถใช้งานได้ ไชโย!
jcalz

58

วิธีแก้ปัญหาที่ง่ายที่สุดคือการใช้ Record

type OptionRequirements = Record<Options, OptionRequirement>

คุณยังสามารถใช้งานได้ด้วยตัวเองในรูปแบบ:

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

โครงสร้างนี้จะใช้ได้เฉพาะกับแต่ไม่typeinterface

ปัญหาในคำจำกัดความของคุณคือการบอกว่าคีย์ของอินเทอร์เฟซของคุณควรเป็นประเภทenum อยู่Optionsที่ไหนOptionsไม่ใช่สตริงตัวเลขหรือสัญลักษณ์

key in Optionsหมายถึง "สำหรับผู้ที่ปุ่มเฉพาะที่อยู่ในตัวเลือกประเภทสหภาพ"

typeinterfaceนามแฝงที่มีความยืดหยุ่นมากขึ้นและมีประสิทธิภาพมากกว่า

ถ้าชนิดของคุณไม่จำเป็นต้องนำมาใช้ในชั้นเรียนให้เลือกมากกว่าtypeinterface


5

ฉันมีปัญหาที่คล้ายกัน แต่กรณีของฉันมีคุณสมบัติฟิลด์อื่นในอินเทอร์เฟซดังนั้นโซลูชันของฉันจึงเป็นตัวอย่างที่มีคุณสมบัติฟิลด์ที่เป็นทางเลือกพร้อม enum สำหรับคีย์:

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

แทนที่จะใช้อินเทอร์เฟซให้ใช้ประเภทวัตถุที่แมป

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

ในกรณีของฉันฉันต้องการคุณสมบัติเป็นทางเลือกดังนั้นฉันจึงสร้างประเภททั่วไปนี้

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

จากนั้นใช้มันดังนี้:

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

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

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

ตัวอย่าง

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

0

ฉันมีปัญหาที่คล้ายกัน ฉันพยายามใช้เฉพาะคีย์เฉพาะเมื่อสร้างเครื่องมือตรวจสอบความถูกต้องของรูปแบบเชิงมุม

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

export type FormError = keyof typeof FormErrorEnum;

และการใช้งาน:

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

ซึ่งจะช่วยให้สามารถใช้คีย์ได้ 1 - X

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.