TypeScript
Useful Helper Types
ts
/*
Must include at least one attribute. The source object should use optional fields.
How to use:
type MyObject = {
name?: string
firstName?: string
}
type Another = AtLeastOne<MyObject, "name" | "firstName">
*/
type AtLeastOne<T, K extends keyof T> = {
[key in K]: Required<Pick<T, key>>
}[K];
/*
Allow exactly one key from a required object type.
How to use:
type MyObject = {
name: string
firstName: string
}
type Another = OnlyOne<MyObject>
*/
type OnlyOne<T> = {
[K in keyof T]:
Pick<T, K> &
Partial<Record<Exclude<keyof T, K>, never>>
}[keyof T];
// Array must not be empty.
type NonEmptyArray<T> = [T, ...T[]];
// Extract a type from another type.
type NewType = Extract<ReferredType, { someAttribute: unknown }>["someAttribute"];
// Declare a component type in Vue.
type ActionButtonType = InstanceType<typeof ActionButton> | undefined;Useful tsconfig Settings
json
{
"compilerOptions": {
"baseUrl": ".", // Set the base URL to the project root.
"paths": {
"~/*": ["src/*"] // Alias "~/commons/utils" to "src/commons/utils".
},
"moduleResolution": "node", // Use Node.js module resolution.
"esModuleInterop": true // Enable ES module interop for default imports.
}
}Minimal Strict Config
tsconfig.json
json
{
"compilerOptions": {
/* Language and Environment */
"target": "ESNext",
/* Modules */
"module": "ES2022",
"rootDir": "./src",
"moduleResolution": "node",
"baseUrl": "./src",
"paths": {
"*": ["./*"]
},
/* Emit */
"outDir": "./dist",
/* Interop Constraints */
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
/* Type Checking */
"strict": true,
"skipLibCheck": true
}
}Vue and Neovim
NOTE
The TypeScript plugin workaround below was useful in older Neovim and Volar setups. Keep it only if your current editor still needs it.
sh
npm install -D typescript @vue/typescript-pluginjson
{
"compilerOptions": {
"plugins": [
{
"name": "@vue/typescript-plugin"
}
]
}
}TypeScript and JavaScript Tips
globalThis
windowonly exists in browsers.globalonly exists in Node.js.globalThisworks across browsers, Node.js, workers, and edge runtimes.
typeof
Use typeof when a global may not exist at all.
js
console.log(typeof globalThis.crypto !== "undefined");
// true or false, with no ReferenceError
console.log(globalThis.someNonExistentProperty !== undefined);
// false, because the property lookup is allowed
console.log(someNonExistentProperty !== undefined);
// ReferenceError: someNonExistentProperty is not definedUsing typeof globalThis.crypto !== "undefined" prevents this error because typeof never throws an error even if the property is missing.