Typescript: Perbaikan cepat untuk 'serikat pekerja tidak dapat digunakan dalam tanda tangan indeks, gunakan jenis objek yang dipetakan'

Dibuat pada 17 Mei 2018  ·  37Komentar  ·  Sumber: microsoft/TypeScript

Kode berikut:

type K = "foo" | "bar";

interface SomeType {
    [prop: K]: any;
}

Memberikan pesan kesalahan ini:

An index signature parameter type cannot be a union type. Consider using a mapped object type instead.

Tidak ada yang tahu apa itu tipe objek yang dipetakan, jadi mari kita beri mereka perbaikan cepat

  • Mengalihkan tanda tangan indeks ke tipe yang dipetakan
  • Memindahkan anggota lain ke tipe objek terpisah yang digabungkan dengan tipe persimpangan
  • Mengubah tipe objek yang memuat menjadi alias tipe jika tipe objek yang memuat adalah antarmuka
  • Berpotongan dengan semua klausa extends jika tipe objek yang memuatnya adalah antarmuka dan memiliki extends klausa
Error Messages Quick Fixes Moderate Fixed Suggestion help wanted

Komentar yang paling membantu

Kamu bisa melakukan ini:

type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any};

Meskipun Bar tidak memiliki tanda tangan indeks (yaitu, Anda tidak dapat melakukan (obj as Bar)[value as Foo] ).

Sunting: Meskipun jika Anda bisa membuat peringatan bukan masalah, saya akan berterima kasih selamanya!

Semua 37 komentar

Tidak ada yang tahu apa itu tipe objek yang dipetakan, jadi mari kita beri mereka perbaikan cepat

+1, baru saja datang ke sini karena saya mengharapkan 2.9 untuk mendukung serikat sebagai tanda tangan indeks sesuai kode contoh Anda. Saya rasa ini telah lama menjadi fitur yang diinginkan: # 5683, # 16760, dll.

Kamu bisa melakukan ini:

type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any};

Meskipun Bar tidak memiliki tanda tangan indeks (yaitu, Anda tidak dapat melakukan (obj as Bar)[value as Foo] ).

Sunting: Meskipun jika Anda bisa membuat peringatan bukan masalah, saya akan berterima kasih selamanya!

saya ingin mengerjakan ini: tertawa:

Memindahkan anggota lain ke tipe objek terpisah yang digabungkan dengan tipe persimpangan

apa yang harus kita lakukan jika berisi tipe objek adalah kelas?
Saya hanya bisa membayangkan bahwa itu adalah sebuah antarmuka

jadi apa yang harus dilakukan mengikuti kode setelah quickfix?

type K = "1" | "2"

class SomeType {
    a = 1;
    [prop: K]: any;
}

jadi apa yang harus dilakukan mengikuti kode setelah quickfix?

Saya akan mengatakan ini seharusnya tidak bisa diperbaiki ..

@mhegazy Saya menggunakan 3.0.0-rc dan masih mendapatkan kesalahan yang sama seperti aslinya. Apakah ini diharapkan?

Saya menggunakan 3.0.0-rc dan masih mendapatkan kesalahan yang sama seperti aslinya. Apakah ini diharapkan?

Iya. kesalahannya benar. Masalah ini melacak penambahan perbaikan cepat untuk itu, yaitu bubur kertas di sebelah pesan kesalahan.

tidak ada tindakan kode yang tersedia dengan 2.9.1 dan vscode

@ThaJay Kami tidak akan mendukung fitur ini, coba atur versi yang lebih baru.

Jelas sekali. Saya minta maaf karena tidak memeriksa timeline terlebih dahulu, hanya menganggap itu cukup baru. Baru di ts. Akan memeriksa dengan versi 3.

bagaimana menjelaskan ini:

function createRequestTypes(base){
  return ['REQUEST', 'SUCCESS', 'FAILURE'].reduce((acc, type) => {
    acc[type] = `${base}_${type}`
    return acc
  }, {})
}

const user = createRequestTypes('USER')
console.log(user.REQUEST) // error
// just string? like:
interface IRequestType: {[key: string]: string}

Saya mencoba di bawah ini, semua gagal:

type requestStatus = 'REQUEST' | 'SUCCESS' | 'FAILURE'
type requestTypes = {
  [key in requestStatus]: string
}
// or
interface IRequestTypes {[key: keyType]: string}
// or even
type requestTypes = {
  FAILURE: string,
  SUCCESS: string,
  REQUEST: string
}

@maicWorkGithub ini dia:

const user = createRequestTypes('USER')
console.log(user.REQUEST) 

function createRequestTypes(base:string):requestTypes {
  const result : requestTypes    = {}
  const arr    : requestStatus[] = ['REQUEST', 'SUCCESS', 'FAILURE']  

  return arr.reduce((acc, type) => {
    acc[type] = `${base}_${type}`
    return acc
  }, result)
}


type requestStatus = 'REQUEST' | 'SUCCESS' | 'FAILURE'
type requestTypes = { [key in requestStatus]?: string }

@ihorsky Terima kasih !!

Hanya ingin tahu mengapa type berfungsi, tetapi interface tidak. Bisakah seseorang menjelaskan, tolong? Apa alasan untuk batasan (atau fitur?) interface .

type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any}; // ok
interface Baz {[key in Foo]: any} // =>

// A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.ts(1169)
// A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)
// 'Foo' only refers to a type, but is being used as a value here.ts(2693)

Ini adalah perbaikan otomatis yang luar biasa untuk ditemukan. Terima kasih telah menerapkannya! :)

Sama untuk kelas.

Kamu bisa melakukan ini:

type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any};

Meskipun Bar tidak memiliki tanda tangan indeks (yaitu, Anda tidak dapat melakukan (obj as Bar)[value as Foo] ).

Sunting: Meskipun jika Anda bisa membuat peringatan bukan masalah, saya akan berterima kasih selamanya!

Gunakan Record sebagai gantinya!

type Foo = 'a' | 'b'
type Bar = Record<Foo, any>

Untuk menambahkan satu contoh lagi menggunakan kelas ...

class Foo {
   a: string;
   b: string;
}

type Bar = {[key in keyof Foo]: any};

bahkan lebih baik jika menggunakan Parsial

type A = 'x' | 'y' | 'z';
type M = Partial<{
    [key in A]: boolean
}>;

Tidak ada yang tahu apa itu tipe objek yang dipetakan, jadi mari kita beri mereka perbaikan cepat

@Bayu_joo
Mengapa pesan kesalahan tidak dapat memberikan jawaban, mis. Tunjukkan contoh cepat menggunakan tipe yang dipetakan - yang hanya terdiri dari beberapa baris kode yang akan konsisten dengan panjang rata-rata pesan kesalahan Ketikan: trollface:

apakah ada yang tahu jika mungkin untuk mengatakan bahwa antarmuka yang menggunakan tipe atau enum sebagai kunci hanya dapat menerima satu properti?

Misalnya tanda tangan seperti ini: { <field>: { <and|or|xor>: <int> } } diambil dari operator mongo bitwise .

export enum BitwiseOperator {
    and = "and",
    or = "or",
    xor = "xor",
}

export type BitwiseCondition = {
    [key in BitwiseOperator]?: number;
}

Kemudian ketika menggunakannya, saya ingin memvalidasi bahwa variabel yang ditentukan oleh antarmuka, hanya memiliki satu properti.

const query: BitwiseCondition = {
  and: 5,
  or: 6  // raise a ts error
};

@ b4dnewz Anda tidak dapat melakukannya dalam Ketikan. Solusi: https://github.com/Microsoft/TypeScript/issues/10575

@ b4dnewz , jika anda hanya menginginkan 1 properti, mengapa tidak dilakukan seperti ini?

export enum BitwiseOperator {
  and = "and",
  or = "or",
  xor = "xor",
}

export type BitwiseCondition = {
  operator: BitwiseOperator;
  value: number;
}

@benwinding sayangnya bentuk yang dikembalikan berbeda dari yang diharapkan mongodb

@apieceofbart terima kasih atas sarannya, saya telah

Saya mencoba untuk menjaga definisi mongo-operator sesederhana mungkin untuk menghindari sakit kepala saya 😁 mungkin di masa depan dukungan yang tepat ditambahkan

@ b4cfdh

Mungkin opsi yang lebih sederhana yang mungkin dapat Anda gunakan adalah:

export type BitwiseCondition =
  | { or: number }
  | { xor: number }
  | { and: number }

Itu tentang hal terdekat yang akan Anda dapatkan tanpa terlalu banyak duplikasi

@ b4cfdh

Mungkin opsi yang lebih sederhana yang mungkin dapat Anda gunakan adalah:

export type BitwiseCondition =
  | { or: number }
  | { xor: number }
  | { and: number }

Itu tentang hal terdekat yang akan Anda dapatkan tanpa terlalu banyak duplikasi

Ini tidak akan menghasilkan kesalahan dalam contoh ini:

const query: BitwiseCondition = {
  and: 5,
  or: 6  // raise a ts error
};

Saya pikir itu intinya

@bayu_joo ,

Ini tidak akan menghasilkan kesalahan dalam contoh ini:

export type BitwiseCondition =
  | { or: number }
  | { xor: number }
  | { and: number }

const query: BitwiseCondition = {
  and: 5,
  or: 6  // doesn't raise a ts error!
};

Wow! itu aneh: open_mouth: Saya tidak tahu itu!

Tampaknya Typecript tidak mendukung tipe yang saling eksklusif untuk objek. Ini juga merupakan proposal untuk bahasa di sini: https://github.com/microsoft/TypeScript/issues/14094

Ini masih mungkin secara teknis ...

Dari jawaban stackoverflow ini dimungkinkan untuk mencapai ini dengan menggunakan tipe kondisional (

/*
 XOR boiler plate
*/
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = T | U extends object
  ? (Without<T, U> & U) | (Without<U, T> & T)
  : T | U;
type XOR3<S, T, U> = XOR<S, XOR<T, U>>;

// Code start
export type BitwiseCondition = XOR3<
  { or: number },
  { xor: number },
  { and: number }
>;

const query1: BitwiseCondition = {
  and: 5
};

const query: BitwiseCondition = {
  and: 5,
  or: 6 // raise a ts error
};

Jika ada yang bisa membuat ini lebih cantik atau lebih baik, tolong lakukan

@mvasin FWIW, _muncul_ ini untuk mencapai hasil yang sama, tetapi saya setuju sepenuhnya bahwa ini harus menjadi fitur antarmuka seperti pada tipe.

type Foo = 'a' | 'b';

type Bar = {
  [key in Foo]: any
}

interface A extends Bar { }

class Wol implements A{
  a: any;
  b: any;
}

Untuk skrip ketikan 3.5, sepertinya saya harus melakukan ini:

export interface DataTableState {
  columnStats: {[key in keyof DataTable]?:{}}
}

Apakah ini cara terbaik untuk melakukan ini?

Mengapa sebenarnya tanda tangan indeks tidak bisa menggunakan tipe enum? Jenis yang dipetakan hampir melakukan apa yang saya inginkan, tetapi kemudian TypeScript mengharapkan setiap string dari enum ada sebagai kunci yang ditentukan. Saya sebenarnya tidak ingin menegaskan bahwa setiap kunci ada, lebih dari itu jika ada kunci, mereka harus tinggal di enum.

Misalnya untuk tipe:

type MyType = {
  [Key: 'foo' | 'bar' | 'zip']: number;
};

Ini harus memuaskan:

const x: MyType = {
  foo: 1,
  zip: 2
};

Meskipun saya hanya dapat menetapkan kunci lain yang tidak ditentukan untuk jenis yang dipetakan, saya lebih suka menjadikan kunci tersebut opsional, tetapi jika ada, nilainya tidak dapat ditentukan. Jika saya membuat nilai tipe yang dipetakan sebagai opsional, kodenya berfungsi tetapi tipenya kurang kuat.

bahkan lebih baik jika menggunakan Parsial

type A = 'x' | 'y' | 'z';
type M = Partial<{
    [key in A]: boolean
}>;

Terima kasih!
Berguna saat Anda perlu menentukan jenis yang cocok sebagian dengan kamus

"Parsial" juga dapat digunakan di Records:

type Foo = 'a' | 'b';
let foo1: Record<Foo, number> = { a: 1, b: 2 };
let foo2: Partial<Record<Foo, number>> = { a: 1 };

Saya menemukan diri saya tanpa disadari mengunjungi halaman GitHub ini setiap bulan atau lebih.

Yang terbaru saya sangat sederhana:

interface ObjectLiteral {
    [key: string | number]: any
}
export const mapToObjectLiteral = (map: Map<string|number, any>) =>
    Array.from(map).reduce((objLit, [key, value]) => {
        objLit[key] = value
        return objLit
    }, {} as ObjectLiteral)

image

Saya dapat menggulir ke atas dan mencari solusi, tetapi hanya ingin memberikan umpan balik bahwa masalah ini sering terjadi dalam pekerjaan sehari-hari dalam skenario yang sedikit berbeda.

berikut ini contohnya:

type MapKey = string | number;
type ObjectLiteral<T extends MapKey, V = any> = {
  [P in T extends number ? string : T]: V;
};

export const mapToObjectLiteral = <T extends MapKey, V>(map: Map<T, V>) =>
  Array.from(map).reduce((objLit, [key, value]) => {
    objLit[key as keyof ObjectLiteral<T>] = value;
    return objLit;
  }, {} as ObjectLiteral<T, V>);

// how to make a better type of map ?
const m = new Map<1 | "foo", "a" | "b">();
m.set(1, "a");
m.set("foo", "b");

const o = mapToObjectLiteral(new Map(m));

console.log(o[1], o.foo); // just got an union type of every member of 'o'

https://github.com/microsoft/TypeScript/issues/24220#issuecomment -504285702

Untuk menambahkan satu contoh lagi menggunakan kelas ...

class Foo {
   a: string;
   b: string;
}

type Bar = {[key in keyof Foo]: any};

Sangat berguna. Terima kasih! 🚀

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

MartynasZilinskas picture MartynasZilinskas  ·  3Komentar

dlaberge picture dlaberge  ·  3Komentar

Zlatkovsky picture Zlatkovsky  ·  3Komentar

siddjain picture siddjain  ·  3Komentar

uber5001 picture uber5001  ·  3Komentar