Skip to content

Infer Types for Generic Type Parameters That Are Not Specified #43119

@ITenthusiasm

Description

@ITenthusiasm

Suggestion

Infer types for generic type parameters that are not specified.

🔍 Search Terms

Search Inputs:

  • infer, type, for, record
  • I have read the FAQs for feature requests.

Search Time: 21:01.23 (21 minutes)

Potentially related issues (in order of interest):

Though related, I couldn't tell if these issues were exactly the same since the scope here is more narrow.

✅ Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

The third one threw me off a little. But since the suggestion bases itself on existing TS features, I think this should be safe.

⭐ Suggestion

This is a suggestion to infer types for generic type parameters that are not specified. As an example for clarity, you can play with the code below on the typescript playground:

function genericFunction<V = unknown, K extends string = string>(arg: Record<K,V>) {
    return arg;
}

const input = { a: 1, b: 2 };

// Property names ARE inferred
genericFunction(input);

// Property names NOT inferred
genericFunction<number>(input);

In the above example, you'll noticed that when no type parameters are provided, TypeScript is able to correctly infer the types on its own. This thankfully includes the property names of the passed object.

However, when any type parameters are provided, TS assumes the default values for all of the remaining type parameters. This actually causes information to be lost, even though the situation hasn't changed. That is, in both situations, the user never explicitly specified the type of the keys, K.

Instead of assuming the default values for the remaining parameters whenever any types are specified, TS should continue to infer types for the remaining type parameters. The current functionality makes me assume there's some algorithm that tries to infer the types when no type parameters are specified, and it's able to infer object keys. I'd imagine that same algorithm can simply be taken and used to "move down the list of type parameters", so to speak. So it would look for any remaining unspecified types and infer them instead of applying the default values.

📃 Motivating Example

Improved Type Inference for Generics

Previously, when working with optional generic type parameters, TypeScript would assume the default values for any types that the user failed to specify. The issue only occurred if the user specified some of the type parameters. This caused information to be lost (particularly for objects) if the user wanted to specify only a subset of the available types.

Now, TypeScript correctly infers the types for type parameters that are not explicitly provided by the user. The default value is only used if one cannot be determined.

const object = { a: 1, b: 2 };

function foo<Value = unknown, Key extends string = string>(input: Record<Key,Value>): Record<Key, Value> {
  // ...
}

// Object correctly typed as Record<"a" | "b", number> instead of Record<string, number>
const output = foo<number>(object);

💻 Use Cases

Currently, packages like React JSS rely on TS to improve the user experience. In the case of React JSS, a user supplies an object of key-value pairs, where the values represent CSS styles for components. Users have to keep track of the keys because they're used to identify the different styles. See the React JSS playground for a clear example.

As you'll see in the playground, the class names can be inferred for an improved experience. However, after receiving a request for improved prop-type recognition (cssinjs/jss#1273), the library needs to include generic types. Once generics are introduced, users will get type inference for React prop types but will then lose automated inference for object keys, recreating the issue of poor intellisense.

The only workaround for this issue is to supply a list of strings ("A" | "B" | "C") as a type parameter for the class names. But this can get long with a larger number of style declarations, and it's redundant.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions