Рассмотрим следующий тип:
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
и скажем, я хочу создать тип, который расширяет вышеупомянутый тип в Record<keyof Collections, unknown>
Я знаю, что typescript недавно представил оператор statisfies, но это полезно только для const не расширения самих типов.
Я знаю форму желаемого типа, т.е.
export type SubCollections = {
cards: [CardLog, CardActions]
users: [UserLog]
}
это работает, однако это не очень практично, потому что, когда я хочу использовать функцию
const subcollection = <K extends keyof Collections, S extends SubCollections[K]>(
collection: K,
sub: S
) => // ...
Это вызывает TypeError:
Тип
Kнельзя использовать индексный типSubCollections
Что, очевидно, я понимаю, почему это происходит. Я знаю, что мог бы создать искусственный более узкий тип, т.е.
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!
Но это все еще кажется довольно неуклюжим, если бы мне приходилось индивидуально сужать аргумент в каждом отдельном случае использования.
Возможно, я мог бы сказать машинописному тексту, что два типа используют одни и те же ключи?
// something akin to (obviously this is invalid syntax)
export type SubCollections extends Record<keyof Collections, unknown[]> = {
cards: [CardLog, CardActions]
users: [UserLog]
}
Нет прямого отношения. Может быть любым объектом для любых намерений и целей. Единственная прямая связь заключается в том, что Коллекции и Подколлекции имеют одни и те же ключи (точнее, ключ Подколлекции должен быть ключом Коллекции, но это не точная карта (т.е. некоторые ключи могут быть опущены)
Но... эти два типа не используют одни и те же ключи, и поэтому вы получаете сообщение об ошибке... Что, если K в вашем примере означает "бизнес"? Тогда неразумно использовать его как ключ к SubCollections.






Это может помочь?
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) => {};
Обновление благодаря Вере:
const subcollection = <K extends keyof Collections & keyof SubCollections, S extends SubCollections[K]>(
collection: K,
sub: S
) => {};
Теперь кажется так просто...
Commonkeys можно записать как keyof A & keyof B.
Вауу. я не знал этого
Какая связь между Card, CardActions и CardLog и User с UserLog?