Skip to content

Fix types of automatic and classic runtimes #11

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

Merged
merged 5 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
* @typedef {string|number|null|undefined} XPrimitiveChild
* @typedef {Array.<Node|XPrimitiveChild>} XArrayChild
* @typedef {Node|XPrimitiveChild|XArrayChild} XChild
* @typedef {import('./jsx-classic').Element} x.JSX.Element
* @typedef {import('./jsx-classic').IntrinsicAttributes} x.JSX.IntrinsicAttributes
* @typedef {import('./jsx-classic').IntrinsicElements} x.JSX.IntrinsicElements
* @typedef {import('./jsx-classic').ElementChildrenAttribute} x.JSX.ElementChildrenAttribute
*/

export * from './jsx-classic.js'

/**
* Create XML trees in xast.
*
Expand Down
10 changes: 2 additions & 8 deletions lib/jsx-automatic.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import {XAttributes, XChild, XResult} from './index.js'

/**
* This unique symbol is declared to specify the key on which JSX children are passed, without conflicting
* with the Attributes type.
*/
declare const children: unique symbol

export namespace JSX {
/**
* This defines the return value of JSX syntax.
Expand All @@ -32,7 +26,7 @@ export namespace JSX {
/**
* The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type.
*/
[children]?: XChild
children?: XChild
}
}

Expand All @@ -43,6 +37,6 @@ export namespace JSX {
/**
* Only the key matters, not the value.
*/
[children]?: never
children?: never
}
}
68 changes: 33 additions & 35 deletions lib/jsx-classic.d.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import {XAttributes, XChild, XResult, x} from './index.js'
import {XAttributes, XChild, XResult} from './index.js'

/**
* This unique symbol is declared to specify the key on which JSX children are passed, without conflicting
* with the Attributes type.
*/
declare const children: unique symbol

export namespace JSX {
/**
* This defines the return value of JSX syntax.
*/
type Element = XResult
/**
* This defines the return value of JSX syntax.
*/
export type Element = XResult

/**
* This disallows the use of functional components.
*/
type IntrinsicAttributes = never
/**
* This disallows the use of functional components.
*/
export type IntrinsicAttributes = never

/**
* This defines the prop types for known elements.
*
* For `xastscript` this defines any string may be used in combination with `xast` `Attributes`.
*
* This **must** be an interface.
*/
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
interface IntrinsicElements {
[name: string]:
| XAttributes
| {
/**
* The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type.
*/
[children]?: XChild
}
}
/**
* This defines the prop types for known elements.
*
* For `xastscript` this defines any string may be used in combination with `xast` `Attributes`.
*
* This **must** be an interface.
*/
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
export interface IntrinsicElements {
[name: string]:
| XAttributes
| {
/**
* The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type.
*/
[children]?: XChild
}
}

/**
* The key of this interface defines as what prop children are passed.
*/
export interface ElementChildrenAttribute {
/**
* The key of this interface defines as what prop children are passed.
* Only the key matters, not the value.
*/
interface ElementChildrenAttribute {
/**
* Only the key matters, not the value.
*/
[children]?: never
}
[children]?: never
}
4 changes: 4 additions & 0 deletions test-d/automatic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,9 @@ expectError(<a invalid={{}} />)
expectError(<a invalid={[1]} />)
expectError(<a>{{invalid: 'child'}}</a>)

// This is where the automatic runtime differs from the classic runtime.
// The automatic runtime the children prop to define JSX children, whereas it’s used as an attribute in the classic runtime.
expectType<Result>(<a children={<b />} />)

declare function Bar(props?: Record<string, unknown>): Element
expectError(<Bar />)
9 changes: 5 additions & 4 deletions test-d/classic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import {x} from '../index.js'

type Result = Element | Root

// To do: fix classic types.
/* eslint-disable @typescript-eslint/no-unsafe-argument */
expectType<Result>(<></>)
expectType<Result>(<a />)
expectType<Result>(<a b="c" />)
Expand Down Expand Up @@ -40,7 +38,10 @@ expectError(<a invalid={{}} />)
expectError(<a invalid={[1]} />)
expectError(<a>{{invalid: 'child'}}</a>)

// This is where the classic runtime differs from the automatic runtime.
// The automatic runtime the children prop to define JSX children, whereas it’s
// used as an attribute in the classic runtime.
expectError(<a children={<b />} />)

declare function Bar(props?: Record<string, unknown>): Element
expectError(<Bar />)

/* eslint-enable @typescript-eslint/no-unsafe-argument */