CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-config-universe

Shared ESLint configs for internal Expo projects providing multiple presets for different environments.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

typescript-analysis.mddocs/

TypeScript Type-Aware Linting

Optional enhanced TypeScript linting configuration that utilizes parsed type information for more sophisticated analysis. Provides advanced type-aware rules that can catch complex type-related issues but requires additional setup and may increase linting time.

Capabilities

TypeScript Analysis Configuration

Advanced TypeScript linting rules that require type information from the TypeScript compiler.

// Traditional ESLint config (.eslintrc.js)
module.exports = {
  extends: [
    'universe', // or universe/native, universe/web, universe/node
    'universe/shared/typescript-analysis'
  ],
  overrides: [
    {
      files: ['*.ts', '*.tsx', '*.d.ts'],
      parserOptions: {
        project: './tsconfig.json'
      }
    }
  ]
};

// Flat Config (ESLint 9+)
const { defineConfig } = require('eslint/config');
const universeConfig = require('eslint-config-universe/flat/default'); // or /native, /web, /node
const typescriptAnalysisConfig = require('eslint-config-universe/flat/shared/typescript-analysis');

module.exports = defineConfig([
  ...universeConfig,
  {
    ...typescriptAnalysisConfig,
    languageOptions: {
      ...typescriptAnalysisConfig.languageOptions,
      parserOptions: {
        project: './tsconfig.json'
      }
    }
  }
]);

Configuration Requirements:

  • Must specify parserOptions.project pointing to your tsconfig.json
  • Extends the base TypeScript configuration with additional type-aware rules
  • Requires TypeScript compiler to be available for type checking
  • Only applies to TypeScript files (*.ts, *.tsx, *.d.ts)

Usage Examples:

// Basic TypeScript project with type-aware linting
// .eslintrc.js
module.exports = {
  extends: [
    'universe',
    'universe/shared/typescript-analysis'
  ],
  overrides: [
    {
      files: ['*.ts', '*.tsx', '*.d.ts'],
      parserOptions: {
        project: './tsconfig.json'
      }
    }
  ]
};

// Multi-package monorepo setup
// .eslintrc.js
module.exports = {
  extends: [
    'universe/node',
    'universe/shared/typescript-analysis'
  ],
  overrides: [
    {
      files: ['packages/*/src/**/*.ts'],
      parserOptions: {
        project: ['packages/*/tsconfig.json']
      }
    }
  ]
};

// React Native project with type analysis
// .eslintrc.js
module.exports = {
  extends: [
    'universe/native',
    'universe/shared/typescript-analysis'
  ],
  overrides: [
    {
      files: ['src/**/*.{ts,tsx}'],
      parserOptions: {
        project: './tsconfig.json'
      }
    }
  ]
};

Type-Aware Rules

Async/Await Safety

// Ensures await is used with Promises
'@typescript-eslint/await-thenable': 'warn'

// Prevents unnecessary awaiting of non-Promise values
'@typescript-eslint/no-unnecessary-type-assertion': 'warn'

// Enforces proper return await usage
'no-return-await': 'off'  // Disabled in favor of TypeScript version
'@typescript-eslint/return-await': ['error', 'always']

Examples:

// ❌ await-thenable violations
await 42;                    // Warning: awaiting non-Promise
await 'string';              // Warning: awaiting non-Promise

// ✅ Correct usage
await Promise.resolve(42);   // OK: awaiting actual Promise
await fetch('/api/data');    // OK: fetch returns Promise

// ❌ return-await violations  
async function bad() {
  return Promise.resolve(42); // Error: should use 'return await'
}

// ✅ Correct usage
async function good() {
  return await Promise.resolve(42); // OK: proper return await
}

Promise Handling

// Ensures Promises are properly handled
'@typescript-eslint/no-floating-promises': 'warn'

// Prevents misuse of Promises in conditions
'@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }]

// Enforces error handling
'@typescript-eslint/only-throw-error': 'warn'

Examples:

// ❌ no-floating-promises violations
fetch('/api/data');          // Warning: Promise not handled
Promise.resolve(42);         // Warning: Promise not handled

// ✅ Correct usage
await fetch('/api/data');    // OK: awaited
fetch('/api/data').catch(console.error); // OK: error handled
void fetch('/api/data');     // OK: explicitly ignored

// ❌ no-misused-promises violations
if (Promise.resolve(true)) { } // Error: Promise in condition

// ✅ Correct usage
if (await Promise.resolve(true)) { } // OK: awaited first

Type Assertions and Checks

// Prevents confusing non-null assertions
'@typescript-eslint/no-confusing-non-null-assertion': 'warn'

// Prevents unnecessary type assertions
'@typescript-eslint/no-unnecessary-type-assertion': 'warn'

// Prevents confusing void expressions
'@typescript-eslint/no-confusing-void-expression': 'warn'

Examples:

// ❌ Confusing non-null assertion
if (!(obj!.prop)) { }        // Warning: confusing negation with !

// ✅ Correct usage  
if (!obj!.prop) { }          // OK: clear intent
if (!(obj?.prop)) { }        // OK: optional chaining

// ❌ Unnecessary type assertion
const num = 42 as number;    // Warning: already number
const str: string = 'hello' as string; // Warning: redundant

// ✅ Correct usage
const num = 42;              // OK: type inferred
const element = document.getElementById('id') as HTMLElement; // OK: needed

Array and Iteration Safety

// Prevents for-in loops on arrays
'@typescript-eslint/no-for-in-array': 'error'

// Enforces proper includes usage
'@typescript-eslint/prefer-includes': 'warn'

// Encourages string methods over indexOf
'@typescript-eslint/prefer-string-starts-ends-with': 'warn'

Examples:

// ❌ no-for-in-array violation
const arr = [1, 2, 3];
for (const item in arr) {    // Error: use for-of for arrays
  console.log(item);
}

// ✅ Correct usage
for (const item of arr) {    // OK: for-of for arrays
  console.log(item);
}

// ❌ prefer-includes violation
if (arr.indexOf(item) !== -1) { } // Warning: use includes

// ✅ Correct usage
if (arr.includes(item)) { }  // OK: more readable

// ❌ prefer-string-starts-ends-with violation  
if (str.indexOf('prefix') === 0) { } // Warning: use startsWith

// ✅ Correct usage
if (str.startsWith('prefix')) { } // OK: clearer intent

Modern TypeScript Features

// Encourages nullish coalescing
'@typescript-eslint/prefer-nullish-coalescing': 'warn'

// Encourages optional chaining
'@typescript-eslint/prefer-optional-chain': 'warn'

// Encourages const assertions
'@typescript-eslint/prefer-as-const': 'warn'

// Encourages readonly for arrays that don't change
'@typescript-eslint/prefer-readonly': 'warn'

// Encourages ts-expect-error over ts-ignore (traditional config only)
'@typescript-eslint/prefer-ts-expect-error': 'warn'

// Additional flat config rules
'@typescript-eslint/ban-ts-comment': 'warn'

Examples:

// ❌ prefer-nullish-coalescing violation
const value = input || 'default'; // Warning: may not handle 0, false correctly

// ✅ Correct usage
const value = input ?? 'default'; // OK: only null/undefined trigger default

// ❌ prefer-optional-chain violation
if (obj && obj.prop && obj.prop.method) { } // Warning: use optional chaining

// ✅ Correct usage  
if (obj?.prop?.method) { } // OK: cleaner optional chaining

// ❌ prefer-as-const violation
const colors = ['red', 'blue'] as string[]; // Warning: use as const

// ✅ Correct usage
const colors = ['red', 'blue'] as const; // OK: preserves literal types

// ❌ prefer-ts-expect-error violation
// @ts-ignore
const result = riskyOperation(); // Warning: use @ts-expect-error

// ✅ Correct usage
// @ts-expect-error Known issue with library types
const result = riskyOperation(); // OK: documents expected error

Performance Considerations

Type-aware linting requires TypeScript compilation and can significantly increase linting time:

  • Small projects: Usually acceptable overhead
  • Large projects: May want to run type-aware rules separately or in CI only
  • Monorepos: Consider selective application to specific packages
  • Development: May want to disable for faster feedback during development

Configuration Tips

Selective Application

// Apply only to specific directories
overrides: [
  {
    files: ['src/**/*.ts', '!src/**/*.test.ts'],
    extends: ['universe/shared/typescript-analysis'],
    parserOptions: { project: './tsconfig.json' }
  }
]

CI-Only Usage

// Separate config for CI with full type checking
// .eslintrc.ci.js
module.exports = {
  extends: ['.eslintrc.js', 'universe/shared/typescript-analysis'],
  overrides: [
    {
      files: ['**/*.{ts,tsx}'],
      parserOptions: { project: './tsconfig.json' }
    }
  ]
};

Multiple TSConfig Support

// Support for multiple TypeScript configurations
overrides: [
  {
    files: ['src/**/*.ts'],
    parserOptions: { project: './src/tsconfig.json' }
  },
  {
    files: ['tools/**/*.ts'],
    parserOptions: { project: './tools/tsconfig.json' }
  }
]

Install with Tessl CLI

npx tessl i tessl/npm-eslint-config-universe

docs

basic-config.md

extension-utilities.md

index.md

native-config.md

node-config.md

typescript-analysis.md

web-config.md

tile.json