TypeScript: Bir tipten yalnızca dizi tipi olan anahtarları ve değerleri nasıl çıkarabilirim


Sadece değeri bir dizi olan bir nesnenin özelliklerini çıkarmak için bazı koşullar üretmek istiyorum.

Örneğin:

type Person = {
   name: string
   addresses: Address[]
   age: number
   phoneNumbers: PhoneNumber[]
}

PullOutArrays<Person> => {
   phoneNumbers: PhoneNumber[]
   addresses: Address[]
}

Buna benzer bir şeyi denedim ama nafile:

type PulledOutArrays<T extends Record<string, unknown>> = {
  [K in keyof T]: T[K] extends unknown[] ? T[K] : never
}

Cevap #1

Bu GitHub sorunundan alıntı yapmak:

type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];

type FilteredProperties<T, U> = { [K in FilteredKeys<T, U>]: T[K]; };

type PullOutArrays<T> = FilteredProperties<T, unknown[]>;

type Person = {
  name: string
  addresses: string[]
  age: number
  phoneNumbers: number[]
}

type PersonKeys = FilteredKeys<Person, unknown[]>;

// "addresses" | "phoneNumbers"

type PersonArrays = PullOutArrays<Person>;

// {
//    addresses: string[];
//    phoneNumbers: number[];
// }

Orijinal denemenizden görebileceğiniz gibi, koşullu ifadeyi eşledikten sonra elde ettiğiniz şey:

{ [P in keyof T]: T[P] extends U ? P : never }

Tüm özellik anahtarlarını içeren bir arayüzdür, ancak dizi olmayan türler never olarak değiştirilmiştir, görünüşe göre TS başlangıçta özellik anahtarlarına atanmış türleri kontrol etmediği için. Sonuna bir indeks ekleyerek, derleyiciyi özelliğin değerini okumasını ve nihayetinde sonucu bundan çıkarmasını zorlamış olursunuz.

Oluşturulan birliği kullanarak, ardından bu birlikten orijinal arayüz üzerinde yeni bir eşlenmiş tür oluşturabilirsiniz.

Cevap #2

Veya TS 4.1+ kullanıyorsanız, değere bağlı olarak anahtarı never olarak belirterek anahtarları kaldırmak daha doğrudan bir yaklaşım olabilir:

type OnlyArraysPerson = {
  [K in keyof Person as Person[K] extends unknown[] ? K : never]: Person[K]
}

Daha genel olmak gerekirse:

type OnlyArrays<T> = {
 [K in keyof T as T[K] extends unknown[] ? K : never]: T[K]
}

type ArrayPerson = OnlyArrays<Person>

Oyun alanı

İlgili makaleler