Skip to content

Add JSX support in type definition #3

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 11 commits into from
Dec 9, 2020
51 changes: 46 additions & 5 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// TypeScript Version: 3.7

import {Attributes, Element, Node} from 'xast'
import * as xast from 'xast'

type Children = string | Node | Children[]
type Children = string | xast.Node | Children[]

/**
* Create XML trees in xast.
*
* @param name Qualified name. Case sensitive and can contain a namespace prefix (such as rdf:RDF).
* @param children (Lists of) child nodes. When strings are encountered, they are mapped to Text nodes.
*/
declare function xastscript(name: string, ...children: Children[]): Element
declare function xastscript(name: string, ...children: Children[]): xast.Element

/**
* Create XML trees in xast.
Expand All @@ -21,8 +21,49 @@ declare function xastscript(name: string, ...children: Children[]): Element
*/
declare function xastscript(
name: string,
attributes?: Attributes,
attributes?: xast.Attributes,
...children: Children[]
): Element
): xast.Element

/**
* This namespace allows to use `xastscript` as a JSX implementation.
*
* This namespace is only used to support the use as JSX. It’s **not** intended for direct usage.
*/
declare namespace xastscript.JSX {
/**
* This defines the return value of JSX syntax.
*/
type Element = xast.Element

/**
* This disallows the use of
*/
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`.
*/
interface IntrinsicElements {
[key: string]: xast.Attributes & {
/**
* The prop that matches `ElementChildrenAttribute` key defines the type of JSX children, defines the children type.
*/
''?: Children
}
}

/**
* The key of this interface defines as what prop children are passed.
*/
interface ElementChildrenAttribute {
/**
* Only the key matters, not the value.
*/
'': never
}
}

export = xastscript
38 changes: 38 additions & 0 deletions types/test.ts → types/test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/** @jsx x */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {Attributes, Element} from 'xast'
import x = require('xastscript')

x('urlset') // $ExpectType Element
Expand All @@ -20,6 +23,41 @@ x('urlset', {xmlns}, x('loc'), x('loc')) // $ExpectType Element
x('urlset', {xmlns}, [x('loc'), x('loc')]) // $ExpectType Element
x('urlset', {xmlns}, []) // $ExpectType Element

// $ExpectType Element
const jsx0 = <urlset />
// $ExpectType Element
const jsx1 = <urlset xmlns={xmlns} />
// $ExpectType Element
const jsx2 = <urlset>string</urlset>
// $ExpectType Element
const jsx3 = <urlset>{['string', 'string']}</urlset>
// $ExpectType Element
const jsx4 = (
<urlset>
<loc />
string
</urlset>
)
// $ExpectType Element
const jsx5 = (
<urlset>
<loc />
</urlset>
)
// $ExpectType Element
const jsx6 = (
<urlset>
<loc />
<loc />
</urlset>
)
// $ExpectType Element
const jsx7 = <urlset>{[<loc />, <loc />]}</urlset>
// $ExpectType Element
const jsx8 = <urlset>{[]}</urlset>

declare function Bar(props?: Attributes): Element
const bar = <Bar /> // $ExpectError
x() // $ExpectError
x(false) // $ExpectError
x('urlset', x('loc'), {xmlns}) // $ExpectError
1 change: 1 addition & 0 deletions types/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"jsx": "react",
"lib": ["es2015"],
"noImplicitAny": true,
"noImplicitThis": true,
Expand Down