generated from garrettmills/template-npm-typescript
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
45 lines
1.6 KiB
45 lines
1.6 KiB
|
|
// ============ An implementation of first() ============
|
|
|
|
/**
|
|
* Get the type of the ith element of a tuple.
|
|
* Kind: Vector -> number -> *
|
|
*/
|
|
type ElementOf<Arr extends unknown[], Index extends keyof Arr> = Arr[Index]
|
|
|
|
// An example - this returns the type of the second element of the tuple
|
|
// In this case, literal values are types (kinda), so this resolves to the literal type 'hello'
|
|
// That is, it is satisfiable by the subset of strings {hello}
|
|
// In an editor like VSCode, hover over the name of the type to see what it resolved to
|
|
type ExampleElementOf = ElementOf<[true, 'hello', 3.14], 1>
|
|
|
|
// This succeeds because the value 'hello' is assignable to the type 'hello'
|
|
const exampleElementGood: ExampleElementOf = 'hello'
|
|
|
|
// This fails because the value 'fubar' is not assignable to the type 'hello'
|
|
// const exampleElementBad: ExampleElementOf = 'fubar'
|
|
|
|
/**
|
|
* Accepts non-empty tuples.
|
|
* Does this by coercing the inferred tuple Arr to the intersection type Arr with an interface
|
|
* that MUST have an index 0 which has the type of the first element of Arr.
|
|
* Kind: Vector -> *
|
|
*/
|
|
type NonEmpty<Arr extends unknown[]> = Arr & { 0: ElementOf<Arr, 0> }
|
|
|
|
/**
|
|
* Gets the first element of a non-empty tuple.
|
|
*
|
|
* Accepts a parameter `arr` of type `NonEmpty<Arr>` where `Arr` is the inferred
|
|
* type of the tuple.
|
|
*
|
|
* @param arr
|
|
*/
|
|
function first<Arr extends unknown[]>(arr: NonEmpty<Arr>): ElementOf<Arr, 0> {
|
|
return arr[0]
|
|
}
|
|
|
|
const firstNumber = first([3.14]) // => type: number
|
|
const firstString = first(['hello', 3.14]) // => type: string
|
|
// const firstEmpty = first([]) // => type: never
|