Skip to content

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.