Samuel Hulla
Samuel Hulla

Reputation: 7119

Can I extend a type with another type?

Consider the following type:

export type Collections = {
  users: User
  business: Business
  permissions: Permissions
  cards: Card
}

// note the Collections[keyof Collections] are just some custom types
// that are objects, but are irrelevant for the question

and let's say I want to create a type that extends the aforementioned type in Record<keyof Collections, unknown>

I know recently introduced the statisfies operator, but that is only useful for const not extending the types themelves.

I know the shape of my desired type, i.e.

export type SubCollections = {
  cards: [CardLog, CardActions]
  users: [UserLog]
}

this works, however it's not very practical, because when I want to use a function

const subcollection = <K extends keyof Collections, S extends SubCollections[K]>(
  collection: K,
  sub: S
) => // ...

This throws a TypeError:

Type K cannot be used index type SubCollections

Which obviously I understand why it happens. I know I could create an artificial type-narrower i.e.

type SharedKey<K extends keyof Collection> = K extends keyof SubCollections
 ? K
 : never

export const subcollection = <
  K extends keyof Collections,
  S extends SharedKey<K>
>(collection: K, subcol: S) => // ...
// ^ this works!

But this still feels rather clumsy if I had to individually narrow the argument in every single use-case.

Is there perhaps a way I could tell typescript, that the two types share the same keys?

// something akin to (obviously this is invalid syntax)
export type SubCollections extends Record<keyof Collections, unknown[]> = {
  cards: [CardLog, CardActions]
  users: [UserLog]
}

Upvotes: 0

Views: 332

Answers (1)

Romain TAILLANDIER
Romain TAILLANDIER

Reputation: 2015

Is this might helps ?

type Commonkeys<A, B> = keyof A extends infer keyofA ? (keyofA extends keyof B ? keyofA : never) : never;

type AAA = Commonkeys<Collections, SubCollections>;
//  type AAA = "cards" | "users"

const subcollection = <K extends Commonkeys<Collections, SubCollections>, S extends SubCollections[K]>(collection: K, sub: S) => {};

Update thanks to vera :

    const subcollection = <K extends keyof Collections & keyof SubCollections, S extends SubCollections[K]>(
  collection: K,
  sub: S
) => {};

Seems so simple now ...

Upvotes: 1

Related Questions