Skip to content

Instantly share code, notes, and snippets.

/**
* This approach has many limitations:
* - it does not accept variable names with numbers or other symbols (relatively easy to fix)
* - it does not accept arbitrary expressions (quite difficult to fix)
*/
function deferredTemplateLiteral(template: string, env: { [key: string]: string | undefined }): string {
const varsMatcher = /\${([a-zA-Z_]+)}/
const globalVarsmatcher = /\${[a-zA-Z_]+}/g
const varMatches: string[] = template.match(globalVarsmatcher) ?? []
@castarco
castarco / composableNominalTypes.ts
Last active March 11, 2021 12:59
Composable Nominal Types for Typescript
export type ChainNominal<BaseType, Tag extends string> = BaseType extends {
__type: infer Tag0
__baseType: infer BaseType0
}
? Tag0 extends [...infer NestedTags]
? BaseType0 & { __type: [Tag, ...NestedTags]; __baseType: BaseType0 }
: never
: BaseType & {
__type: [Tag] // Using an array allow us to use multiple type tags :3
__baseType: BaseType // Only here to ease type inference
// We use symbols to eliminate any chance for problems with serialization
const __BaseType: unique symbol = new Symbol('__BaseType')
const __Brand: unique symbol = new Symbol('__Brand')
// We mark the "brand/flavor" fields as readonly to avoid anyone doing weird stuff with them
// We add a "__BaseType" field to make possible "complex" type manipulations
// We accept "symbol" tags as a mechanism to avoid "types forgery" to bypass the type checker,
// although I foresee that most of the times it won't be used.
export type Branded<BaseType, Tag extends string | symbol> = BaseType & {
readonly [__BaseType]: BaseType
@castarco
castarco / TypedRegistryPattern.ts
Last active February 9, 2022 13:13
A "new" pattern to create fully-typed registries/containers!
// This first file contains the first iteration of this pattern. It's already
// nice, but not enough for full-fledged IoC libraries.
// There's a second file in this same gist that goes one step further, although,
// for now, it still needs some extra polish.
// -----------------------------------------------------------------------------
// First: the two main interfaces.
// They are the core of the pattern.
// -----------------------------------------------------------------------------
export interface WritableRegistry {
[init]
defaultBranch = main
[commit]
gpgsign = true
template = ${HOME}/.gitmessage
[push]
gpgSign = if-asked
[log]
showSignature = true