Typescript: Membuat tipe dari nilai dalam array

Dibuat pada 22 Okt 2018  ·  16Komentar  ·  Sumber: microsoft/TypeScript


TypeScript Version: 3.0.3


Istilah Pencarian: Ketik berdasarkan nilai dalam larik

Apakah ada fitur saat ini atau yang direncanakan untuk membuat tipe dari string dalam array?

Kode

const values = ['A', 'B']
type Foo = OneOf<values> // Is there a way of doing this?

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

Mirip dengan cara kerja keyof :

const values = {
  A: 'A',
  B: 'B'
}
type Foo = keyof typeof values
const v1: Foo = 'A'
const v2: Foo = 'D' // Type '"D"' is not assignable to type '"A" | "B"'

Masalah Terkait:https://github.com/Microsoft/TypeScript/issues/20965

Tautan ke taman bermain http://www.typescriptlang.org/play/#src = biarkan% 20vals1% 20% 3D% 20% 5B'A '% 2C% 20'B'% 5D% 0D% 0 Jenis% 20Foo1% 20% 3D% 20OneOf% 3Cvals1% 3E% 20% 2F% 2F% 20Is% 20there% 20a% 20way% 20of% 20doing% 20this% 3F% 0D% 0A% 0D% 0Alet% 20v1% 3A% 20Foo1% 20% 3D% 20 ' A '% 20% 2F% 2F% 20Ini% 20harus% 20work% 0D% 0Alet% 20v2% 3A% 20Foo1% 20% 3D% 20'D'% 20% 2F% 2F% 20Ini% 20harus% 20memberikan% 20me% 20an% 20 kesalahan% 20 sejak% 20'D '% 20tidak% 20 ada% 20in% 20 nilai% 0D% 0A% 0D% 0Alet% 20vals2% 20% 3D% 20% 7B% 0D% 0A% 20% 20A% 3A% 20'A '% 2C% 0D% 0A% 20% 20B% 3A% 20'B'% 0D% 0A% 7D% 0D% 0 Jenis% 20Foo2% 20% 3D% 20keyof% 20type% 20vals2% 0D% 0Alet% 20v3% 3A% 20Foo2 % 20% 3D% 20'A '% 0D% 0Alet% 20v4% 3A% 20Foo2% 20% 3D% 20'D'% 20% 2F% 2F% 20Type% 20 '% 22D% 22'% 20is% 20not% 20 assignable % 20 hingga% 20 jenis% 20 '% 22A% 22% 20% 7C% 20% 22B% 22'

Question

Komentar yang paling membantu

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Semua 16 komentar

keyof hanya berfungsi karena menggunakan informasi yang diketahui secara statis pada waktu kompilasi. Jenis di TS sepenuhnya dapat dihapus dan tidak ada dalam kode yang ditranspilasi, jadi tidak mungkin untuk membuat jenis berdasarkan konten runtime dari sebuah larik.

Ini mungkin:

function stringLiterals<T extends string>(...args: T[]): T[] { return args; }
type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType> ? ElementType : never;

const values = stringLiterals('A', 'B');
type Foo = ElementType<typeof values>;

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

Jelas tidak jelas bagaimana melakukan ini. # 27179 terkait.

Itu masih menggunakan informasi yang dikenal secara statis oleh kompilator; pada saat itu saya tidak mengerti apa keuntungan dari sekedar mengatakan ”A” | “B” .

@fatcerberus Berguna untuk menghindari pengulangan informasi - jika Anda hanya menulis const values = ["A", "B"]; type Foo = "A" | "B"; , mudah bagi seseorang untuk mengubah salah satunya sementara lupa untuk mengubah yang lain. Anda dapat menulis const values: Foo[] =["A", "B"]; , tetapi itu masih rentan dengan menambahkan entri tambahan ke Foo dan lupa memasukkannya ke dalam values .

Di mana kita sekarang?

Seperti yang dikatakan @ andy-ms, akan sangat berguna untuk menghindari pengulangan informasi secara manual.
Dan seperti yang dikatakan @fatcerberus , tipe sepenuhnya dapat dihapus. Terkadang kita perlu memeriksa data runtime yang kita dapatkan misalnya dari bagian aplikasi yang tidak murni (seperti layanan web, atau dari pengguna).

Berdasarkan jawaban @ andy-ms, dan menggunakan pernyataan konstanta yang diperkenalkan dalam skrip ketikan 3.4, sekarang mungkin untuk melakukan sesuatu seperti ini

const values = ['A', 'B'] as const
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
  infer ElementType
>
  ? ElementType
  : never

type Foo = ElementType<typeof values> // this is correctly inferred as literal "A" | "B"

Masalah ini telah ditandai sebagai 'Pertanyaan' dan tidak melihat aktivitas terbaru. Itu telah ditutup secara otomatis untuk keperluan rumah tangga. Jika Anda masih menunggu jawaban, pertanyaan biasanya lebih cocok untuk stackoverflow .

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Daripada ini:

export const items = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof items[number];
}

Kamu bisa melakukan ini:

export const items = [
  'room',
  'room_with_gifter',
  'user_send'
] as const;

export type Item = typeof items;

export interface Activity {
  id?: string;
  type: Item;
}

image

_Sangat tidak suka menggunakan type sebagai nama variabel._

@ 7

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Sekarang bagaimana jika saya memiliki ini di kelas?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

Tidak bekerja. Saya juga tidak bisa melakukan this.list[number] . Juga, khusus saya
usecase, saya tidak dapat menyetel list menjadi static

@ 7

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Sekarang bagaimana jika saya memiliki ini di kelas?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

Tidak bekerja. Saya juga tidak bisa melakukan this.list[number] . Juga, khusus saya
usecase, saya tidak dapat menyetel list menjadi static

@vegerot Anda tidak dapat menggunakan const secara langsung dalam lingkup class , jadi sintaksnya salah.

@ 7

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Sekarang bagaimana jika saya memiliki ini di kelas?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

Tidak bekerja. Saya juga tidak bisa melakukan this.list[number] . Juga, khusus saya
usecase, saya tidak dapat menyetel list menjadi static

@vegerot Anda tidak dapat menggunakan const secara langsung dalam lingkup class , jadi sintaksnya salah.

@ 7Saya buruk. Saya menyalin dan menempel terlalu banyak. Yang ingin saya katakan adalah

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

dll semua tidak bekerja.
Juga, untuk kasus penggunaan khusus saya, saya tidak dapat menyetel daftar menjadi statis

@ 7

di [email protected] dan di atasnya. selesaikan seperti ini

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

Sekarang bagaimana jika saya memiliki ini di kelas?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

Tidak bekerja. Saya juga tidak bisa melakukan this.list[number] . Juga, khusus saya
usecase, saya tidak dapat menyetel list menjadi static

@vegerot Anda tidak dapat menggunakan const secara langsung dalam lingkup class , jadi sintaksnya salah.

@ 7Saya buruk. Saya menyalin dan menempel terlalu banyak. Yang ingin saya katakan adalah

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

dll semua tidak bekerja.
Juga, untuk kasus penggunaan khusus saya, saya tidak dapat menyetel daftar menjadi statis

class Class {
  private list = [
    "room",
    "room_with_gifter",
    "user_send"
  ] as const

  private withType: Class["list"][number]
}

@vegerot Bagaimana dengan ini?

@eyal itu luar biasa! Terima kasih. Saya pikir solusinya akan melibatkan typeof atau sesuatu. Apakah Anda akan memberikan penjelasan singkat tentang cara kerjanya, atau tautkan saya ke buku pegangan di mana hal ini dibahas?

@eyal itu luar biasa! Terima kasih. Saya pikir solusinya akan melibatkan typeof atau sesuatu. Apakah Anda akan memberikan penjelasan singkat tentang cara kerjanya, atau tautkan saya ke buku pegangan di mana hal ini dibahas?

@vegerot Tentu, saya yakin ini adalah "Jenis indeks". Ini dia di Buku Pegangan: https://www.typescriptlang.org/docs/handbook/advanced-types.html#index -types

Senang aku dapat membantu!

Hai% username%, jika ElementType solusi juga tidak berfungsi untuk Anda,
perhatikan as const after array . Ini penting

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

rbuckton picture rbuckton  ·  139Komentar

rwyborn picture rwyborn  ·  210Komentar

RyanCavanaugh picture RyanCavanaugh  ·  205Komentar

yortus picture yortus  ·  157Komentar

disshishkov picture disshishkov  ·  224Komentar