简体   繁体   中英

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, ie

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 ie

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]
}

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM