#array of generic types, extract generic to union

1 messages · Page 1 of 1 (latest)

cinder ledgeBOT
#
ricmed#0

Preview:```ts
class Box<V> {}

function fn1(...boxes: Array<Box>) {
// ...
}

// x must be :: string | number
const x = fn1(new Box<string>(), new Box<number>())
...```

eager haven
#

here's one approach:

cinder ledgeBOT
#
mkantor#0

Preview:```ts
class Box<V> {
v: V
}

type WhatsInTheBox<B extends Box<unknown>> =
B extends Box<infer T> ? T : never
declare function fn1<A extends Array<Box<unknown>>>(
...boxes: A
): WhatsInTheBox<A[number]>

// x must be :: string | number
const x = fn1(new Box<string>(), new Box<number>())
...```

frosty tide
#

technically don't need to index, can just do

type Unwrap<T> = T extends Box<infer U>[] ? U : never

afaik

eager haven
#

true. i'd probably slap a readonly on that constraint though otherwise i'd get confused later when i try to use it with an as const array

eager haven
#
type Unwrap<T> = T extends readonly Box<infer U>[] ? U : never
subtle lotus
#

sorry, this part "otherwise i'd get confused later when i try to use it with an as const array"

eager haven
#

ah, i was talking about situations like this:

cinder ledgeBOT
#
class Box<V> { v!: V }
type Unwrap<T> = T extends Box<infer U>[] ? U : never

const boxes = [new Box<number>(), new Box<string>()] as const
type Womp = Unwrap<typeof boxes>
//   ^? - type Womp = never
eager haven
#

because T[] extends readonly T[], but not the other way around

#

i've tried to get into the habit of basically always using readonly array types in parameters and generic constraints (unless i actually need mutability), because it inevitably comes back to bite me later if i don't

#

it's strictly more general

eager haven
#

it makes sense if you think about it this way: T[] is readonly T[] plus methods like push, pop, etc. so it's a subtype

subtle lotus
#

thank you both!