Melihat dokumentasi TypeScript di URL ini https://www.typescriptlang.org/docs/handbook/advanced-types. html

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

Dapatkah seseorang menjelaskan kepada saya apa arti [keyof T] ini setelah kurung kurawal penutup? Apakah ada dokumentasi untuk sintaks ini?

0
Dmitri 4 Januari 2021, 19:22

3 jawaban

Jawaban Terbaik

keyof T berarti kunci yang valid untuk tipe T (Anda mungkin tahu itu). Bila Anda memiliki [x] setelah antarmuka atau jenis gabungan, ia memilih jenis properti/anggota dengan nama x. Misalnya (

interface Example {
    a: number;
    b: string;
}
type E1 = Example["a"];
/*
type E1 = number;
*/

Sejauh yang saya tahu, "tipe pencarian" ini hanya didokumentasikan dalam catatan rilis TypeScript 2.1 di sini:

keyof dan Jenis Pencarian Dalam JavaScript, cukup umum untuk memiliki API yang mengharapkan nama properti sebagai parameter, tetapi sejauh ini tidak mungkin untuk mengekspresikan hubungan tipe yang terjadi di API tersebut.

Masukkan Kueri Jenis Indeks atau keyof; Kueri tipe terindeks keyof T menghasilkan tipe nama properti yang diizinkan untuk T. Tipe keyof T dianggap sebagai subtipe string.

Contoh

interface Person {
  name: string;
  age: number;
  location: string;
}

type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ...
type K3 = keyof { [x: string]: Person }; // string

Dual dari ini adalah tipe akses yang diindeks, juga disebut tipe pencarian. Secara sintaksis, mereka terlihat persis seperti akses elemen, tetapi ditulis sebagai tipe:

Contoh

type P1 = Person["name"]; // string
type P2 = Person["name" | "age"]; // string | number
type P3 = string["charAt"]; // (pos: number) => string
type P4 = string[]["push"]; // (...items: string[]) => number
type P5 = string[][0]; // string

Anda dapat menggunakan pola ini dengan bagian lain dari sistem tipe untuk mendapatkan pencarian yang aman untuk tipe.

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]; // Inferred type is T[K]
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
  obj[key] = value;
}

let x = { foo: 10, bar: "hello!" };

let foo = getProperty(x, "foo"); // number
let bar = getProperty(x, "bar"); // string

let oops = getProperty(x, "wargarbl"); // Error! "wargarbl" is not "foo" | "bar"

setProperty(x, "foo", "string"); // Error!, string expected number

Bagian utama FunctionPropertyNames<T> menghasilkan antarmuka dengan anggota bertipe never untuk semua properti T yang tidak bertipe fungsi, dan tipe anggota asli untuk semua properti yang bertipe fungsi. Misalnya, seperti yang ditunjukkan pada contoh, jika Anda melakukan ini:

interface Part {
  id: number;
  name: string;
  subparts: Part[];
  updatePart(newName: string): void;
}

type T1 = FunctionPropertyNames<Part>;

T1 akhirnya menjadi "updatePart" karena itulah satu-satunya kunci T (Part) yang memiliki tipe fungsi. Tanpa bagian [keyof T], Anda akan mendapatkan antarmuka dengan anggota never sebagai gantinya (bermain Link):

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type Example<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}/* Same as above, but without [keyof T] here*/;

interface Part {
  id: number;
  name: string;
  subparts: Part[];
  updatePart(newName: string): void;
}

type T1 = FunctionPropertyNames<Part>;
/*
type T1 = "updatePart"
*/
type E1 = Example<Part>;
/*
type E1 = {
    id: never;
    name: never;
    subparts: never;
    updatePart: "updatePart";
}
*/

Ini adalah bagian [keyof T] yang membuat FunctionPropertyNames memberikan nama dari properti bertipe fungsi, daripada properti bertipe fungsi itu sendiri (dan yang bertipe never ).

0
T.J. Crowder 4 Januari 2021, 16:45

[keyof T] ini mewakili atribut apa pun di dalam T.

Untuk lebih memahami, ambil yang berikut ini:

type AB = {
  aa: number,
  ab: () => number,
  cd: () => number,
  ef: () => number
}

type FunctionPropertyKeyToNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}

/* The only possible value for this 👇 example will be { aa: never, ab: 'ab', cd: 'cd', ef: 'ef' } */
const example: FunctionPropertyKeyToNames<AB> = 

Sekarang, dengan menggunakan [keyof T] kita hanya akan mendapatkan nilainya,
Secara teori never, 'ab', 'cd', 'ef', tetapi karena TypeScript tidak akan menyelesaikan never sebagai nilai untuk Anda
Anda hanya akan mendapatkan 'ab', 'cd', 'ef'

0
Felipe Malara 4 Januari 2021, 16:48

Itu disebut "tipe pencarian".

  1. keyof X mengembalikan semua kunci dari suatu tipe

  2. jika

    interface a {
       foo: never
       bar: string
       baz: number
    }

Maka type not_here = a['foo'] akan menjadi never

Tetapi jenis pencarian juga mendukung penerusan keyof Something, jadi

a[keyof a] akan menjadi gabungan semua jenis kunci/properti a, yaitu never | string | number. Meskipun never tidak memiliki arti di sana sehingga TS secara otomatis mengabaikannya, menghasilkan string | number.

(tentu saja Anda dapat melakukan a[keyof b], tidak ada batasan di sini)

Saya menemukan bahwa cara terbaik untuk mencari tahu jenis kompleks seperti ini adalah untuk menguraikan mereka dalam langkah-langkah seperti yang kulakukan di sini:

interface test {
    a: string
    b: () => void
    c: () => void
}

type T_A<T> = {
  [K in keyof T]: T[K]
};

type T_B<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
};

type T_C<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

type a = T_A<test>
type b = T_B<test>
type c = T_C<test>

Dengan ini Anda dapat melihat langkah-langkah individual yang diambil untuk mendapatkan hasil yang diinginkan, yaitu "penyatuan kunci yang bertipe Fungsi".

0
Sergiu Paraschiv 4 Januari 2021, 16:52