Functions that convert one type of value to another are quite common.
For example, imagine a situation where you have two Position
types from different libraries and you want to create a set of functions to convert from one type to another, and back.
While this might sound like a trivial task, giving these functions an appropriate name is usually an excercise in redundancy:
import * as lsp from "vscode-languageserver-types"
import * as vscode from "vscode"
// this is one possible naming style
function lspPositionToVSCodePosition(p: lsp.Position): vscode.Position {
/*...*/
}
// or maybe like this?
namespace lspPosition {
export function toVSCodePosition(p: lsp.Position): vscode.Position {}
}
And naming it is only a small part of the problem:
lspToVSCodeConverions.ts
, or util.ts
?)The x9.convert
function provides a cleaner alternative. (note: x9.convert is one of a series of type-driven extensions to TypeScript - it relies in the compiler to “inject” code at runtime based on type information. this is a controversial feature)
// the following defines a "conversion" function from one type to another
x9.conversion<lsp.Position, vscode.Position>(
(p) => new vscode.Position(p.line, p.column)
)
// and later, anywhere in your projectconst lspPosition: lsp.Position = {};
// you can simply call x9.convert and pass in the desired type
// the compiler will search for a conversion matching the pair of types (input and output)
// and inject logic if found, or show a compilation error otherwise
const vscodePosition = x9.convert<vscode.Position>(p)
You can also use the @x9.conversion JSDoc annotation
You can optionally turn on implicit conversions. This will eliminate the need for calling x9.convert
altogether.
const p1 = new vscode.Position(0, 0)
// the following typechecks :)
const p2: lsp.Position = p1
const p2 = p1 as lsp.Position
printPosition(p1)
function printPosition(p: lsp.Position) {}