Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autocomplete breaks after one property for an array generic #57879

Open
RareSecond opened this issue Mar 21, 2024 · 3 comments
Open

Autocomplete breaks after one property for an array generic #57879

RareSecond opened this issue Mar 21, 2024 · 3 comments
Labels
Domain: Completion Lists The issue relates to showing completion lists in an editor Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Milestone

Comments

@RareSecond
Copy link

πŸ”Ž 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)[])

@Andarist
Copy link
Contributor

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

@RareSecond
Copy link
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?

@Andarist
Copy link
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).

@RyanCavanaugh RyanCavanaugh added Help Wanted You can do this Domain: Completion Lists The issue relates to showing completion lists in an editor Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases labels Mar 22, 2024
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Domain: Completion Lists The issue relates to showing completion lists in an editor Help Wanted You can do this Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
Development

No branches or pull requests

3 participants