typescript - Cum să: generic care acceptă tipuri readonly?


Având o acțiune asupra unei liste

type DoSomethingWith<L extends any[]> = L

ce încerc să fac funcționează în felul următor

const keys = {
  a: ['a', 'b', 'c'] as ['a', 'b', 'c'],
  d: ['d', 'e', 'f'] as ['d', 'e', 'f'],
}

type Keys = typeof keys

type KeysWithSomething = {
  [K in keyof Keys]: DoSomethingWith<Keys[K]>
}

Dar pentru a evita redundanța (pe ceea ce ar putea fi o listă mai lungă) aș dori să pot să o scriu astfel:

const keys = {
  a: ['a', 'b', 'c'] as const,
  d: ['d', 'e', 'f'] as const,
}

type Keys = typeof keys

type DoSomethingWith<L extends any[]> = L

type KeyKinds = {
  [K in keyof Keys]: DoSomethingWith<Keys[K]>
                                  // ^^^^^^^: Type '{ a: readonly ["a", "b", "c"]; d: readonly ["d", "e", "f"]; }[K]' does not satisfy the constraint 'any[]'.
}

Eroarea este că încerc să trec un tip numai-în-citire la DoSomething care așteaptă un tip generic de listă (any[]). Există vreo modalitate de a specifica pentru DoSomething că ar trebui să accepte și elemente numai-în-citire?

Răspuns #1

Da, poți folosi modificatorul readonly într-o constrângere generică:

type DoSomethingWith<L extends readonly any[]> = L
//                             ^ add this

Sau mergi în sens invers și elimini flag-ul readonly, după ce ai restrâns keys cu as const:

type Mutable<T> = T extends object ? { -readonly [K in keyof T]: Mutable<T[K]> } : T

Testați cu tipurile dvs. (Loc de joacă):

type T1 = Mutable<Keys> // { a: ["a", "b", "c"]; d: ["d", "e", "f"]; }

type KeyKinds = {
    [K in keyof Keys]: DoSomethingWith<Mutable<Keys[K]>> // compiles now
}