UNPKG

@snap/camera-kit

Version:
57 lines 3.35 kB
import type { Container, ContainerToken } from "./Container"; type AsTuple<T> = T extends readonly any[] ? T : never; type CorrespondingService<Services, Token extends ValidTokens<Services>> = Token extends ContainerToken ? Container<Services> : Token extends keyof Services ? Services[Token] : never; /** * Given a Services object, the valid Tokens are simply the keys of that object or the special Container Token. */ export type ValidTokens<Services> = ContainerToken | keyof Services; /** * Given Services, map from a list of Tokens to a list of Service types. */ export type CorrespondingServices<Services, Tokens extends readonly ValidTokens<Services>[]> = { [K in keyof Tokens]: Tokens[K] extends ValidTokens<Services> ? CorrespondingService<Services, Tokens[K]> : never; }; /** * A valid InjectableFunction is one that can be successfully called, given some Services, to return a new Service. That * is, it must satisfy two conditions: * * 1. All the Tokens it specifies as dependencies are valid given the Services (i.e. they are either the Container * Token or keys of the Services type). * 2. The function argument types correspond to the Services specified by the dependency Tokens. * * A InjectableFunction also includes its own key Token and dependency Tokens as metadata, so it may be resolved by * Container<Services> later. */ export type InjectableFunction<Services, Tokens, Token extends string, Service> = Tokens extends readonly ValidTokens<Services>[] ? { (...args: AsTuple<CorrespondingServices<Services, Tokens>>): Service; token: Token; dependencies: Tokens; } : never; export type AnyInjectable = InjectableFunction<any, readonly string[], string, any>; export type ServicesFromInjectables<Injectables extends readonly AnyInjectable[]> = { [Name in Injectables[number]["token"]]: ReturnType<Extract<Injectables[number], { token: Name; }>>; }; /** * Add a Service with a Token to an existing set of Services. */ export type AddService<ParentServices, Token extends string, Service> = ParentServices extends any ? { [K in keyof ParentServices | Token]: K extends keyof ParentServices ? ParentServices[K] : Service; } : never; /** * Create an object type from two tuples of the same length. The first tuple contains the object keys (strings) and the * second contains the value types corresponding to those keys. * * Ex: * ```ts * type FooBar = ServicesFromTokenizedParams<['foo', 'bar'], [string, number]> * const foobar: FooBar = {foo: 'foo', bar: 1} * const badfoobar: FooBar = {foo: 1, bar: 'bar'} // any extra, missing, or mis-typed properties raise an error. * ``` */ export type ServicesFromTokenizedParams<Tokens, Params> = Tokens extends readonly [] ? Params extends readonly [] ? {} : never : Tokens extends readonly [infer Token, ...infer RemainingTokens] ? Params extends readonly [infer Param, ...infer RemainingParams] ? Tokens["length"] extends Params["length"] ? Token extends ContainerToken ? Param extends Container<infer S> ? S & ServicesFromTokenizedParams<RemainingTokens, RemainingParams> : never : Token extends string ? { [K in Token]: Param extends Container<infer S> ? S : Param; } & ServicesFromTokenizedParams<RemainingTokens, RemainingParams> : never : never : never : never; export {}; //# sourceMappingURL=types.d.ts.map