ryansolid / babel-plugin-jsx-dom-expressions

A JSX to DOM plugin that wraps expressions for fine grained change detection
MIT License
60 stars 10 forks source link

Add JSX type defintions #10

Closed r0skar closed 5 years ago

r0skar commented 5 years ago

This PR adds JSX type defintions (fix https://github.com/ryansolid/babel-plugin-jsx-dom-expressions/issues/7) by declaring the JSX namespace in the global scope. Note that the special variable $ is not included, as it cant be typed as JSX element. For now, it must be separately declared as a global variable:

declare const $: (attr: {
  children?: {}
  each?: unknown[]
  when?: boolean
  suspend?: boolean
  fallback?: unknown
  portal?: unknown
  useShadow?: boolean
  provide?: {
    id: symbol
    initFn: () => any
  }
  value?: any
  afterRender?: () => unknown
}) => any

To make use of the typings in a new project, TS needs to know of their existence. This can be achieved in various ways:


// Directly import the plugin.
import * as _ from 'babel-plugin-jsx-dom-expressions'

// Add a reference to the definition file.
/// <reference path="node_modules/babel-plugin-jsx-dom-expressions/types/index.d.ts" />

// Add the plugin dir to the typesRoot array in the tsconfig.json file.
{
  "compilerOptions": {
    "typeRoots": [
      "./node_modules/babel-plugin-jsx-dom-expressions"
    ]
  }
}
ryansolid commented 5 years ago

I see. Is there any way to get the $ as part of these declarations? I guess it doesn't make sense. Could interfere with other global '$'. I'd love if they just need to set up a single reference and they'd have it. Really didn't expect $ to be such a hangup for TypeScript. I chose it since it removed the need for a condition={} on control flow since almost all need an argument passed I figured it would lead to less to write.

r0skar commented 5 years ago

The $ declaration I have posted in my comment could be included in the declaration file. But as you pointed out: it would interfere with other global $ declarations (jquery). As of now, I did not find a way to type it as a JSX element. For now, you could add a how-to for potential users and have them create a d.ts file in their project, that will enable all JSX typings (including $):

import * as _ from 'babel-plugin-jsx-dom-expressions'

// Warning: this may interfere with jQuery...
declare const $: (attr: {
  children?: {}
  each?: unknown[]
  when?: boolean
  suspend?: boolean
  fallback?: unknown
  portal?: unknown
  useShadow?: boolean
  provide?: {
    id: symbol
    initFn: () => any
  }
  value?: any
  afterRender?: () => unknown
}) => any
r0skar commented 5 years ago

Just a quick follow up on why $ cant be typed as a JSX element: it seems that it is being interpreted as an uppercase char, but an Intrinsic Element must start with a lowercase char.

ryansolid commented 5 years ago

Yeah I know. I opened up an issue with them. https://github.com/microsoft/TypeScript/issues/31606

I'm frankly surprised by this behavior. Imagine if you wanted to do say NativeScript with JSX which uses cap case Intrinsic Elements. This is just plain broken as far as I'm concerned.