highlight.js icon indicating copy to clipboard operation
highlight.js copied to clipboard

(TypeScript) Generic is not picked up properly

Open ackvf opened this issue 3 years ago • 10 comments

Describe the issue

Which language seems to have the issue?

typescript, no auto-detection

Are you using highlight or highlightAuto? I don't know what this means.

Sample Code to Reproduce

I tried to reproduce the issue using your jsfiddle, but the typescript generic is not even displaying there ¯\(ツ)/¯.
~~https://jsfiddle.net/x3nzp2rf/~~
updated: https://jsfiddle.net/sm706vyd/2/

I have this code on StackOverflow.

meta: https://meta.stackoverflow.com/questions/420116/typescript-syntax-highlight-with-generic-not-picked-up-properly

first observed issue here: https://stackoverflow.com/questions/72794594/typescript-interface-merging-to-make-an-external-libs-interface-property-more-s/73527814#73527814

```lang-ts
import { useWeb3React as useWeb3React_ } from '@web3-react/core'

export const useWeb3React: <T = any>(key?: string) => Modify<
  ReturnType<typeof useWeb3React_<T>>,
  { chainId: SupportedChainIds }
> = useWeb3React_ as any

declare global {
  type SupportedChainIds = 1 | 4
}
```

Which produces incorrect syntax highlight

import { useWeb3React as useWeb3React_ } from '@web3-react/core'

export const useWeb3React: <T = any>(key?: string) => Modify<
  ReturnType<typeof useWeb3React_<T>>,
  { chainId: SupportedChainIds }
> = useWeb3React_ as any

declare global {
  type SupportedChainIds = 1 | 4
}

After a tweak I achieve correct syntax highlight

import { useWeb3React as useWeb3React_ } from '@web3-react/core'

export const useWeb3React: < T = any >(key?: string) => Modify<
  ReturnType<typeof useWeb3React_<T>>,
  { chainId: SupportedChainIds }
> = useWeb3React_ as any

declare global {
  type SupportedChainIds = 1 | 4
}

This is the tweak:

- export const useWeb3React: <T = any>(key?: string) => Modify<
+ export const useWeb3React: < T = any >(key?: string) => Modify<

Expected behavior

(without the spaces around < T = any > - correct is: <T = any>)

Actual behavior

Additional context

ackvf avatar Aug 29 '22 12:08 ackvf

I tried to reproduce the issue using your jsfiddle, but the typescript generic is not even displaying there ¯(ツ)/¯.

Because you haven't properly escaped < and > in your HTML, etc.

joshgoebel avatar Aug 29 '22 12:08 joshgoebel

Not sure I follow this <T = syntax, could a simpler example be given? I believe the problem is this is detected as HTML starting and the end of the HTML can't ever be found, so the highlighting is broken. JSX and types are very hard to parse without a real parser.

joshgoebel avatar Aug 29 '22 12:08 joshgoebel

#3604 might be a reasonable fix. Thoughts?

joshgoebel avatar Aug 29 '22 12:08 joshgoebel

I updated the jsfiddle where the exact mentioned issue above can be observed. https://jsfiddle.net/sm706vyd/2/

ackvf avatar Aug 31 '22 12:08 ackvf

It can be further reduced to just this, but I find the remaining type definition helpful to showcase the issue.

// Incorrect
export const useWeb3React: <T = any>(key?: string) => any
// Correct
export const useWeb3React: < T = any >(key?: string) => any

ackvf avatar Aug 31 '22 12:08 ackvf

A workaround people usually use, which is accepted by the TS community is adding a comma , at the end of the generic, which is allowed in generics lists, but not allowed in JSX and HTML.

type MyFunction = <T = any>(arg: T) = ({ value: T }) // <- would cause highlighting issues
type MyOtherType = <T, U, V>(arg: T) = ({ a: T, b: U, c: V }) // <- example of correct way to use commas in type generics
type MyFunction = <T = any,>(arg: T) = ({ value: T }) // <- Accepted workaround
type MyOtherType = <T, U, V>(arg: T) = ({ a: T, b: U, c: V }) // <- no workaround needed as it already contains commas

I tried adding the comma there, but it didn't change anything. This would have been preferred over adding spaces.

export const useWeb3React: <T = any,>(key?: string) => any

ackvf avatar Aug 31 '22 12:08 ackvf

Did you glance at the PR? See the description for the strategy we're using.

joshgoebel avatar Aug 31 '22 12:08 joshgoebel

Yes, you could add check for this too ,> or , > e.g. <T,> or <T = any,> or <T extends string,> or <T extends string = 'xyz',>, which is a generally accepted escape hatch in JSX-TS world to make parsers realise this is not JSX but TS.

ackvf avatar Aug 31 '22 13:08 ackvf

As you see from the other issue it seems like if we add the = case that I think now we're covering all the bases?

joshgoebel avatar Sep 01 '22 02:09 joshgoebel

Yeah, I guess so.

ackvf avatar Sep 01 '22 20:09 ackvf