Skip to content

Add strictFunctionTypes to Enhance Type Safety for Function Parameters #58607

Closed

Description

🔍 Search Terms

strict function types TypeScript
TypeScript array union type safety
TypeScript specific to union array assignment
TypeScript union type array assignment error

✅ Viability Checklist

⭐ Suggestion

Introduce a new compiler option, strictFunctionTypes, to enhance type safety for function parameters. This option would prevent assigning specific array types (e.g., string[]) to function parameters expecting broader union types (e.g., (string | number)[]). This change aims to avoid potential runtime errors caused by unintended type mutations, ensuring that arrays maintain their intended types when passed to functions. It'd be a non-breaking change since it'd need to explicitly adding this option to tsconfig.

// TypeScript Configuration (tsconfig.json)
{
  "compilerOptions": {
    "strictFunctionTypes": true // Hypothetical option for stricter checking
  }
}

📃 Motivating Example

Imagine you have a function that accepts an array of either strings or numbers and modifies it. Currently, TypeScript allows you to pass an array of strings to this function, potentially leading to runtime errors when the function adds a number to the array. With the proposed strictFunctionTypes option, TypeScript would prevent this assignment, ensuring type safety and avoiding unexpected mutations.

type StringOrNumber = string | number;

const listOfStrings: string[] = [];

const addToListOfStrings = (list: StringOrNumber[]) => {
  list.push(1); // Adds a number to the list of strings
}

addToListOfStrings(listOfStrings); // Currently allowed, but causes a runtime error

💻 Use Cases

  1. What do you want to use this for?
    API Design and Validation:
    When designing APIs or library functions that accept a union of types, it's crucial to enforce strict type constraints. By not allowing specific array types (e.g., string[]) to be passed to parameters expecting broader union types (e.g., (string | number)[]), developers can ensure that functions handle inputs in a type-safe manner, avoiding unintended mutations and runtime errors.
  2. What shortcomings exist with current approaches?
    Lack of Strict Type Enforcement:
    Currently, TypeScript's type system is flexible, allowing specific types to be passed to parameters expecting union types. This flexibility can lead to unintended side effects, such as modifying an array of strings with a number, which contradicts the intended type of the array. This shortcoming can result in runtime errors and makes it harder to maintain type safety in large or collaborative codebases.
  3. What workarounds are you using in the meantime?
    API Design and Validation:
    To prevent type-related errors, developers often add manual runtime checks within functions to ensure that arrays contain only the expected types before performing operations. While this approach helps avoid some issues, it adds boilerplate code and relies on runtime checks rather than leveraging TypeScript's compile-time type system.
    Example:
const addToListOfStrings = (list: (string | number)[]) => {
  if (list.every(item => typeof item === 'string')) {
    list.push('new string'); // Safe to add a string
  } else {
    throw new Error('List contains non-string elements');
  }
}

Use of generics
Another workaround is to use generics to enforce type constraints more explicitly. However, this approach can become complex and cumbersome for simple use cases.

const listOfStrings: string[] = [];

const addToList = <T extends string | number>(list: T[], item: T): void => {
  list.push(item);
}

addToList(listOfStrings, 'new string'); // Safe
addToList(listOfStrings, 1); // Type error

By implementing the strictFunctionTypes option, TypeScript could automatically enforce these constraints at compile time, reducing the need for manual checks and making the codebase more robust and maintainable.

Activity

  1. fatcerberus commented on May 21, 2024

    @fatcerberus

    strictFunctionTypes already exists and it does something completely different than what you're suggesting.

  2. fatcerberus commented on May 21, 2024

    @fatcerberus

    It looks like you're really looking for something like #14150; the unsoundness described here isn't limited to function calls.

  3. KevBeltrao commented on May 21, 2024

    @KevBeltrao
    Author

    In this case, I'm moving this discussion to that issue! Thanks

  4. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions