This is an old revision of the document!
TS
typehero
declare const config: Chainable
const result = config
.option('foo', 123)
.option('name', 'type-challenges')
.option('bar', { value: 'Hello World' })
.get()
// expect the type of result to be:
interface Result {
foo: number
name: string
bar: {
value: string
}
}
Type Argument Inference in TypeScript
Goal: Understand how TypeScript infers type arguments
type Chainable<T = {}> = {
option<K extends string, V>(key: Exclude<K, keyof T>, value: V): Chainable<Omit<T, K> & {[P in K]: V}>
get(): T
}
Why K is Inferred, Not T?
TypeScript's inference flows from unknown type parameters based on known argument types:
// When you write:
config.option('database', 'mysql')
// TypeScript thinks:
// - Receiver type: Chainable<{}>, so T = {} (KNOWN)
// - First argument: 'database' (literal string)
// → Must infer K = 'database' (UNKNOWN → INFERRED)
// - Second argument: 'mysql' (literal string)
// → Must infer V = 'mysql' (UNKNOWN → INFERRED)
What If T Were Also a Type Parameter?
If we hypothetically made T also inferrable, it would create ambiguity:
// Hypothetical (problematic) design:
type BadChainable = {
option<T, K extends string, V>(
key: Exclude<K, keyof T>,
value: V
): Chainable<Omit<T, K> & {[P in K]: V}>
}
// How would TypeScript know what T should be?
// There would be no way to infer T from the arguments!
The NoInfer Utility Type
function createStreetLight<C extends string>(colors: C[], defaultColor?: C) {
// ...
}
createStreetLight(["red", "yellow", "green"], "blue");
// ^^^^^ defaultColor?: "red" | "yellow" | "green" | "blue" | undefined
// But I don't want blue, because blue is not the color in colors.
// So
function createStreetLight<C extends string>(colors: C[], defaultColor?: NoInfer<C>) {
// ...
}
createStreetLight(["red", "yellow", "green"], "blue");
// ~~~~~~
// error!
// Argument of type '"blue"' is not assignable to parameter of type '"red" | "yellow" | "green" | undefined'.
dokuwiki docker upgrade
tar -czvf "$(date +'%Y-%m-%d_%H-%M-%S')_config.tar.gz" ./config
mv *config.tar.gz ./backup
docker compose down && docker compose pull && docker compose up -d