The AutoComplete Utility Type: Powerful Suggestions Without Restrictions - Advanced TypeScript

Поделиться
HTML-код
  • Опубликовано: 10 дек 2024

Комментарии • 47

  • @xDivisionByZerox
    @xDivisionByZerox 11 дней назад +8

    I provided this suggestion back in October in the same repo as you list in your description as a PR (which is still open as of writing this comment). Kinda sad that you didn't even wrote a message, but glad you found this yourself.

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +3

      I‘m really sorry. I completely missed that. I will look into it an merge it ASAP. Thanks for bringing it up.

    • @dave6012
      @dave6012 11 дней назад +4

      He must have thought it was a lenient suggestion

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +1

      I see what you did there 😁

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +2

      I merged it 🙏

    • @xDivisionByZerox
      @xDivisionByZerox 11 дней назад +1

      No hard feelings. Looking at it now, I can see that the PR description didn't really make clear what I was expecting. I can also see how one can simply check a PR since the project is more of a personal collection than one open for contributions. I'm just glad that a bunch of people can finally learn about this cool feature 🙌

  • @Krikit1337
    @Krikit1337 8 дней назад +2

    For the folks who use typescript-eslint rules that error/warn you this when trying to use {} as a type:
    The `{}` ("empty object") type allows any non-nullish value, including literals like `0` and `""`.
    - If that's what you want, disable this lint rule with an inline comment or configure the 'allowObjectTypes' rule option.
    - If you want a type meaning "any object", you probably want `object` instead.
    - If you want a type meaning "any value", you probably want `unknown` instead.
    You can use NonNullable to get the same type without linting errors

  •  10 дней назад

    Great explanation ever; I also understood abstract type definition!! Thank you v.m!!

  • @SIVA-Mycount
    @SIVA-Mycount 4 дня назад

    The other solution for this Auto completion is omiting the exact type from the string.
    type ComplexLanguage = Language & Omit

  • @ben-sterling
    @ben-sterling 10 дней назад +1

    For this problem, I've used function overloads in the past, but this looks like it could be a nicer pattern in comparison!
    Although I do worry the `& {}` syntax could be a little confusing, whereas fn overloads are quite explicit/clear?
    ```
    type Language = 'JavaScript' | 'TypeScript';
    function setLanguage(arg: string): void
    function setLanguage(arg: Language): void
    function setLanguage(arg: Language | string): void {}
    setLanguage('scr')
    ```

    • @Typed-Rocks
      @Typed-Rocks  10 дней назад

      Maybe it‘s a bit hard at first. But we could wrap this „string | {}“ into it‘s own type

  • @munzamt
    @munzamt 11 дней назад +1

    In general it called brand types. I prefer using another method: you define NonCollapsableWithPrimitive type that accepts generic primitive like string, number etc. And you just chain this with your union type like this:
    type Language = 'JS' | 'TS' | NonCollapsableWithPrimitive
    I think it more readable

  • @rajaark5643
    @rajaark5643 11 дней назад +2

    I need those videos.

  • @haiffy
    @haiffy 11 дней назад +2

    1:52 what extension did you use for that

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад

      It‘s called „twoslash queries“

  • @padcom
    @padcom 11 дней назад +2

    Great example, thanks for showing it. I have another problem similar to this one. Imagine you have an object that can have a set of known keys with their types but could also have other keys, all of another type. Say, type Example = { empty: boolean, [key: string]: string }. How could we type that in TS to get proper auto completion and no compilation errors?

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +1

      I will look into it and come back to you 🤘

    • @ben-sterling
      @ben-sterling 10 дней назад +1

      If the requirement truely is that any other key can be a string, but `empty` must be a boolean, then I don't think this is possible from an "input type" persepctive.
      I'd suggest changing the function to accept two arguments, or nest the `any other key` inside another key. For example:
      `type { empty: boolean, data: Record }`
      However, if this is not an option for whatever reason, you could achieve something similar by creating an impossible type and using a helper fn to create the impossible type in a type-safe way (by accepting 2 args)
      ```ts
      type SpecialRecord = Record & Record;
      // Note, `Exclude` does nothing. It's the same as `string`. I just prefer it because the intent is more clear to humans. eg.
      // type SpecialRecord = Record & Record;
      function run(input: SpecialRecord) {
      const empty = input.empty; // Will correctly show as boolean
      const anyKey = input.anyKey; // Will correctly show as string
      // Your logic here
      }
      // helper fn to create the impossible type
      function createRecord(specialObj: Record, { empty, ...restObj }: Record) {
      return {
      ...restObj,
      ...specialObj,
      } as SpecialRecord;
      }
      run(createRecord({
      empty: false,
      foo: 'foo', // This will error
      }, {
      foo: 'test',
      bar: 'bar',
      empty: 'true', // This will be allowed type-wise, but will be ignored
      baz: true, // This will error (comment out the first error to see)
      }))
      ```

    • @padcom
      @padcom 2 дня назад

      @@ben-sterling Thanks for the example. The reason I'm asking is quite trivial: if you use a Map from Java in an API (swagger), and if that Map is of type then the resulting response is just that - a record that has the field `empty` of type Boolean and anything else of type String. Frankly, I find this case more and more common and if TS would allow for such typing to be made easily, it would make a lot of things much safer.

  • @mrstrangeUser
    @mrstrangeUser 10 дней назад +1

    Need more depth explanation abt *string & {}*

    • @Krikit1337
      @Krikit1337 8 дней назад +1

      I'm not 100% sure on this being accurate, but my understanding is this:
      A union of | is automatically widened by TS into being just -- this is why the any type "corrupts" everything else in a union, because it is the widest type present.
      The "empty object" type {} actually represents "any non-nullish value" -- in other words, any type that is not null or undefined.
      By defining an intersection of string & {}, you effectively create a type that is "as wide as" the string type, but does not inherently widen -- therefore, when you create a union between | , the result is you can have or any string as a value.

  • @idanguttsait
    @idanguttsait 11 дней назад

    I believe this trick was made redundant at one of the last versions, as they made “| string” not erase the specific strings the type consisted of

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад

      I tried that but it does not seem to work

  • @SIVA-Mycount
    @SIVA-Mycount 4 дня назад

    I need exactly help on this one please.In a react I have a AriaRole type that also has this intersection type of string and object. Now I want to create a new type from the AriaRole without this intersection type. I have tried many ways but still couldn't able to omit or Exclude this intersection type. Do you have any solution for this ?

  • @deatho0ne587
    @deatho0ne587 11 дней назад +1

    Remember Matt Pocock talking about this and saying it is really odd. Still personally think it is and do not use it commonly.

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +2

      Like most of the time, it depends. I think it‘s great for certain features where you want to have some suggestions but not be restricted.

    • @deatho0ne587
      @deatho0ne587 11 дней назад

      100% on the use case of it, but the "string & {}" is what we both find odd. Think this was back in TS v4.8 roughly.

  • @jordyperez9969
    @jordyperez9969 10 дней назад

    Do you have a video where you talk about how to make ts flag errors for missing properties within a complex object?
    For example: export interface normalForm {
    rules?: {
    basicValidation?: rules;
    yupValidation?: Yup.Schema;
    };
    toInput?: DynamicTextFieldProps;
    component?: ReactNode;
    grid?: RegularBreakpoints;
    } The toInput property, when I do not set the required properties, does not give me an error in ts, even when setting the toInput prop as required.

    • @Typed-Rocks
      @Typed-Rocks  10 дней назад

      Currently not, but I will look into it 👍

    • @Krikit1337
      @Krikit1337 8 дней назад

      TBH this snippet is lacking a lot of context that would explain why you don't get a TS error, but generally speaking, nested object properties don't have an impact on TS being able to accurately report validation errors unless you're doing something ludicrous or over-using the any type
      If you had explanations of things like the Yup.Schema, DyanmicTextFieldProps, TextFieldPropsType, etc etc...

  • @AndresJimenezS
    @AndresJimenezS 11 дней назад +2

    awesome video!, what if i want the autocomplete but the string must be required ? i mean not empty string?

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад +5

      Then I would suggest to use the never type additionally:
      type NonEmptyString = T extends „“ ? Never : T.
      And then wrap the Autocomplete generic

  • @alexberezkin
    @alexberezkin 8 дней назад

    How does it work? Isn't it a TypeScropt bug?

    • @Typed-Rocks
      @Typed-Rocks  8 дней назад

      No, that‘s how the type system works in typescript. It works as design 👍

    • @alexberezkin
      @alexberezkin 8 дней назад

      @Typed-Rocks is it documented somewhere?

  • @lucasx7292
    @lucasx7292 10 дней назад

    pls, make a video like this, but for objects that have certain keys, but isnt restricted for those keys. something like: type Type = { key1: type, key2: type, [key in string]: any }

    • @Typed-Rocks
      @Typed-Rocks  10 дней назад

      Will look into it. Thank you for your suggestion

    • @Krikit1337
      @Krikit1337 8 дней назад +1

      Generally, that would be Record & { key1: SomeType; key2: SomeOtherType }

  • @shaked1233
    @shaked1233 11 дней назад

    So the autocomplete is available only becuase null and undefined arent allowed? I would like for you to post an explanation on why it works

    • @Typed-Rocks
      @Typed-Rocks  10 дней назад

      I will do a video about it soon 👍

  • @afuzzybearsyoutubechannel2812
    @afuzzybearsyoutubechannel2812 11 дней назад +1

    if u could figure out how to get the keys from a map that would be awesome 👌

    • @Typed-Rocks
      @Typed-Rocks  11 дней назад

      Could you provide an example? Then I will look into it 🤘

    • @Krikit1337
      @Krikit1337 8 дней назад +1

      If you're talking about the JS native Map object, then the only real way to "know" the keys/values are to build your own type over it that either takes in a shape type that you can extract the "keyof" from, or utilizes a builder-style type to provide known key names to a final object