Skip to content

Autocomplete breaks after one property for an array generic #57879

Closed as not planned

Description

@RareSecond

🔎 Search Terms

array generic

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about generics

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.2#code/C4TwDgpgBAsg9gEwgGwMLIIYFcDOEA8AKgHxQC8UA3gFBR1QDyASgPwBcsiK62eRxAbQC6Ablr0AggDkAIu05I0mXARLCxAXygAyKAAUMAJ2ABLDMn5jqoSFABCGPAEUsEQyCJQIAD2AQAdgg4UDjAhib+AOYANFAAql6+AUFQcABGAFYQAMbApBQ09FAAtlzIHIRiRQCOru7y8Io8KvhxxJpWNtBxeIYubiDk9o4Q-e74AEQ9bhOxlFD+GMUQHKHhUSJQGJErC1jFaW5QGu3W4NB6cKE4Y4MUDs51HhOX17NUUKbAyLtrEZGbbJwfx+EGrML-Y6nM62W5DaZ9J5QAA++iuwBuTysADMsP5ciZgZ8IKF-p4fKCUrdiAAKWoDCrCACUVHEdCB-hwcB+ADpkHBInSnkzNNRqLj8aYiX5SVEAEzkpKBYK3YS0+nuCoswr0Dlc3n8wUakAi6gaMUy0xRGkCNmsopFUqKDhTXqzO01J4cHUOh2LZYuy3u32+gD0oaghHAkO20AAFm5oAB3EzIZBbLDAOBA4pgH5+D0h2McACMAAZC3QNNE7dXqEJTdYSVbInKbXafQ6nSgXQjgyHjd7K36lrsJkGayGHeHI+5PtGolsdlAE4YILETMAoEngQByLfYLM5vMQAtTutFOsNsRAA

💻 Code

type ModelClause<T> = {
    OR?: ModelClause<T>[];
    AND?: ModelClause<T>[];
} & Partial<T>;

type BaseQuery<T extends string, U extends object> = {
    model: T;
    query?: ModelClause<U>;
};

type UserQuery = BaseQuery<"User", { name: string; age: number }>;
type PostsQuery = BaseQuery<"Posts", { title: string; content: string }>;

type Query = UserQuery | PostsQuery;

function testing<T extends Query>(query: T[]) {
    console.log(query);
}

function testing2<T extends Query[]>(query: T) {
    console.log(query);
}

testing([
    {
        model: "User",
        query: {
            name: "test",
            // Typing age here will autocomplete
            age: 10
        },
    },
]);

testing2([
    {
        model: "User",
        query: {
            name: "test",
            // Try typing age here, it won't autocomplete
        },
    },
]);

🙁 Actual behavior

For the testing function, you correctly get suggested fields when filling in the query property.

CleanShot 2024-03-21 at 11 57 26

CleanShot 2024-03-21 at 11 57 41

However, for testing2, the suggestion works for your first property, whichever one you try.

CleanShot 2024-03-21 at 11 57 57

CleanShot 2024-03-21 at 11 58 25

However, once the first one is provided, it will stop autocompleting.

CleanShot 2024-03-21 at 11 58 56

Once one has been provided, you can also list any key, regardless of if it's part of the model.

CleanShot 2024-03-21 at 12 00 27

CleanShot 2024-03-21 at 12 00 45

🙂 Expected behavior

It should correctly suggest all properties and typecheck additional properties and not stop working after the first one.

Additional information about the issue

Some extra context why I'm using the testing2 approach, here's a playground link that shows what I'm trying to achieve.

Basically, I want to make sure that the return value of my function adheres to what was passed in. I haven't found a way to do it with testing, so I went for testing2, which is a decrease in DX since it'll only autocomplete one query parameter.

But the return value is exactly what I want

CleanShot 2024-03-21 at 12 10 32

(for reference for others who would stumble upon this issue, the last as const is important to ensure it returns the correct order, else it will have a type of const returnValue: (UserModel | PostModel)[])

Activity

  1. Andarist commented on Mar 21, 2024

    @Andarist
    Contributor

    If you don't need to infer queries then this works reasonably well: TS playground

  2. RareSecond commented on Mar 21, 2024

    @RareSecond
    Author

    Amazing, this works super smooth! Notice for further readers: the correct typing of the tuple will only work on TypeScript >5.4.

    If you would have some spare time, could you explain the differences and why your approach is better?

  3. Andarist commented on Mar 21, 2024

    @Andarist
    Contributor

    With a small adjustment you can also make it work with TS 5.3: TS playground

    If you would have some spare time, could you explain the differences and why your approach is better?

    I think it's better because it gives you a clear way of relating "positional inferences". The query type depends on its own sibling model - you don't even have to create a discriminated union to achieve this. So it's more flexible because you can introduce such dependencies with unknown constraints.

    I don't know why the autocompletes work in this particular way on your two first examples. This might be worth investigating or something. I know though that often autocompletes in objects for optional properties etc might stop working in inference contexts. The problem is that the inferred type (like even {}) is already valid at a particular position and TS sees that type there and not the original constraint based on which it was inferred. So there is no source from which those properties could be obtained. There are some internal ways to query those types with different flags so the constraint can actually often be obtained in such positions but not every call site is querying completions from both types (with inference enabled and with inference blocked on the source location).

  4. RyanCavanaugh commented on Dec 3, 2025

    @RyanCavanaugh
    Member

    Closing language service bugs related to the 6.0 implementation. For more information, see #62827

  5. locked as resolved and limited conversation to collaborators on Dec 3, 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

    7.0 LS MigrationDomain: LS: Completion ListsThe issue relates to showing completion lists in an editorHelp WantedYou can do thisPossible ImprovementThe current behavior isn't wrong, but it's possible to see that it might be better in some cases

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions