Typescript
Useful Helper Type
typescript
// must at least one of attribute
type AtLeastOne<T, K extends keyof T> = {
[key in K]: Required<Pick<T, key>>
}[K]
// array must not empty
type NonEmptyArray<T> = [T, ...T[]];
// extract a type from another type
type NewType = Extract<ReferredType, { someAttribute: unknown }>['someAttribute'];
Useful Config
json
{
"compilerOptions": {
"baseUrl": ".", // Set the base URL to the root of your project
"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
}
}
Minimum config
tsconfig.json
json
{
"compilerOptions": {
/* Language and Environment */
"target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
/* Modules */
"module": "ES2022", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */
"paths": {
"*": ["./*"]
}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
/* Interop Constraints */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
Vue
Neovim
In neovim, after install volar, it still prompt error on typescript file when linked to a vue file. Install package below:
Issue fixed in neovim, no longer need to use
sh
npm install -D typescript @vue/typescript-plugin
Then, change the tsconfig.app.ts
json
{
"compilerOptions": {
"plugins": [
{
"name": "@vue/typescript-plugin"
}
]
}
}
Typescript / Javascript Tips
globalThis
🔥 Why Use globalThis Instead of window or global?
- window → Only exists in browsers, fails in Node.js.
- global → Only exists in Node.js, fails in browsers.
- globalThis → Works in all environments (browser, Node.js, Web Workers, Edge).
typeof
🔥 Why Use typeof? ✅ Prevents ReferenceError if crypto is undefined If you directly check globalThis.crypto !== undefined in an environment where crypto does not exist at all, JavaScript will throw an error:
javascript
console.log(globalThis.someNonExistentProperty !== undefined);
// ✅ No error, returns false
console.log(someNonExistentProperty !== undefined);
// ❌ ReferenceError: someNonExistentProperty is not defined
Using typeof globalThis.crypto !== "undefined" prevents this error because typeof never throws an error even if the property is missing.