/** * @ignore * Binding token for mandatory value */ export type RequiredToken = { symbol: symbol; type?: T; // Anchor for Typescript type inference. isOptional?: false; }; /** * @ignore * Binding token for optional value */ export type OptionalToken = { symbol: symbol; type?: T; // Anchor for Typescript type inference. isOptional: true; optionalValue: T; }; /** * Binding token */ export type Token = RequiredToken | OptionalToken; /** * Token options */ export type TokenOptions = | { /** * Key for token's symbol. It allows to create shareable tokens. */ key: string; /** @ignore */ description?: undefined; } | { /** Description for better error messages */ description?: string; /** @ignore */ key?: undefined; }; /** * Creates a new binding token. * @param description - Token description for better error messages. */ export function token(description?: string): Token; /** * Creates a new binding token. * @param options - Token description for better error messages. */ export function token(options?: TokenOptions): Token; export function token(options?: TokenOptions | string): Token { const normalized: TokenOptions | undefined = typeof options === 'string' ? { description: options } : options; const symbol: symbol = normalized?.key ? Symbol.for(normalized.key) : Symbol(normalized?.description); return { symbol }; } /** * Decorate a token with an optional value. * This value is be used as default value in case a container does not have registered token. * @param token - Existed token. * @param optionalValue - Default value for the resolver. */ export function optional( token: Token, optionalValue: T, ): OptionalToken; export function optional(token: Token): OptionalToken; export function optional( token: Token, optionalValue?: T, ): OptionalToken { return { symbol: token.symbol, isOptional: true, optionalValue, }; }