#How to make type with generic return one type if array and another if not

22 messages · Page 1 of 1 (latest)

frail torrent
#

Imagine I have a type:

type Foo = {
  id: string;
  type: 'foo';
}
type RealtionShipT<T extends Foo | Foo[]> = {
  data: Pick<T, 'id' | 'type'>;   // Do this if T is not an array
  data: Pick<T[number], 'id' | 'type'>; // Do this if T is an array
}

For RelationshipT, I need the type to be the top form if T is NOT an array, but the bottom form if T IS an array. How can I do this?

long lion
#

@frail torrent did you have a look at the docs?

#

basically, you can check if something is an array, and based on that return different types

#
type Foo = {
  id: string;
  type: 'foo';
}
type RealtionShipT<T extends Foo | Foo[]> = {
  data: Pick<T extends any[] ? T[number] : T, 'id' | 'type'>;
}
frail torrent
#

Ah ty!

#

Wait

#
data: T extends ResourceObjectT[]
    ? Pick<T[number], 'id' | 'type'>[]
    : Pick<T, 'id' | 'type'>;
#

This thorws e TS error saying:

#
  Type 'string' is not assignable to type 'keyof T'.
    Type 'string' is not assignable to type 'never'.
#

@long lion not sure what is wrong here

#

but it doesn't like the second half of the ternary

long lion
#

no clue, you should post the entier type @frail torrent

frail torrent
#

I'm sorry, b-post?

long lion
#

*post

frail torrent
#
export type ResourceObjectT = {
  id: string;
  type: string;
  attributes: object;
}
#
export type Relationship<T extends ResourceObjectT | ResourceObjectT[]> = {
  data: T extends any[]
    ? Pick<T[number], 'id' | 'type'>[]
    : Pick<T, 'id' | 'type'>;
};
#

I feel like this should work basted on the docs but it doesn't...

#

@long lion

export type Relationship<T extends ResourceObjectT | ResourceObjectT[]> = {
  data: T extends ResourceObjectT[]
    ? Pick<T[number], 'id' | 'type'>[]
    : T extends ResourceObjectT
    ? Pick<T, 'id' | 'type'>
    : never;
};

This works but it feels like a hack. Not sure why it cannot infer that T in the second half of the ternary must be of type ResourceObject

long lion
#

yeah, idk too well, maybe when excluding the array part from the union TS loses some info in the process

stiff troutBOT
#
ascor8522#0

Preview:```ts
export type ResourceObjectT = {
id: string
type: string
attributes: object
}

type RealtionShipT<
T extends ResourceObjectT | ResourceObjectT[]

= T extends ResourceObjectT[]
? {data: Pick<T[number], "id" | "type">[]}
: {
data: Pick<
Exclude<T, ResourceObjectT[]>,
"id" | "type"

}

...```

long lion
#

weird, since it seems there is narrowing happening in the : part of the ternary, like, if we put data: [...] ? [...] : T, then it output the right T