Skip to content

Commit

Permalink
Lookup JSX namespace within factory function
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Feb 27, 2018
1 parent 32c63a2 commit 488397f
Show file tree
Hide file tree
Showing 16 changed files with 1,560 additions and 114 deletions.
169 changes: 63 additions & 106 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2871,7 +2871,7 @@ namespace ts {
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];

getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNames(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];

Expand Down
2 changes: 1 addition & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@ namespace ts.Completions {
getTypeScriptMemberSymbols();
}
else if (isRightOfOpenTag) {
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNames(), "getJsxIntrinsicTagNames() should all be defined");
const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNames(location), "getJsxIntrinsicTagNames() should all be defined");
if (tryGetGlobalSymbols()) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & (SymbolFlags.Value | SymbolFlags.Alias))));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ declare namespace ts {
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNames(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1811,7 +1811,7 @@ declare namespace ts {
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
getJsxIntrinsicTagNames(): Symbol[];
getJsxIntrinsicTagNames(location: Node): Symbol[];
isOptionalParameter(node: ParameterDeclaration): boolean;
getAmbientModules(): Symbol[];
tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
Property '__predomBrand' is missing in type 'Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,21): error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
Property 'render' is missing in type 'Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,28): error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ children?: Element[]; }'.
Types of property 'children' are incompatible.
Type 'dom.JSX.Element[]' is not assignable to type 'predom.JSX.Element[]'.
Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
Property '__domBrand' is missing in type 'MyClass'.
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
tests/cases/conformance/jsx/inline/index.tsx(24,30): error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ x: number; y: number; children?: Element[]; }'.
Types of property 'children' are incompatible.
Type 'predom.JSX.Element[]' is not assignable to type 'dom.JSX.Element[]'.
Type 'predom.JSX.Element' is not assignable to type 'dom.JSX.Element'.
Property '__domBrand' is missing in type 'Element'.


==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
export namespace dom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__domBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function dom(): dom.JSX.Element;
==== tests/cases/conformance/jsx/inline/renderer2.d.ts (0 errors) ====
export namespace predom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__predomBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function predom(): predom.JSX.Element;
==== tests/cases/conformance/jsx/inline/component.tsx (0 errors) ====
/** @jsx predom */
import { predom } from "./renderer2"

export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;

export class MyClass implements predom.JSX.Element {
__predomBrand!: void;
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
render() {
return <p>
{this.props.x} + {this.props.y} = {this.props.x + this.props.y}
{...this.props.children}
</p>;
}
}
export const tree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

export default <h></h>

==== tests/cases/conformance/jsx/inline/index.tsx (7 errors) ====
/** @jsx dom */
import { dom } from "./renderer"
import prerendered, {MySFC, MyClass, tree} from "./component";
let elem = prerendered;
elem = <h></h>; // Expect assignability error here
~~~~
!!! error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
!!! error TS2322: Property '__predomBrand' is missing in type 'Element'.

const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;

class DOMClass implements dom.JSX.Element {
__domBrand!: void;
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
render() {
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
}
}

// Should work, everything is a DOM element
const _tree = <DOMSFC x={1} y={2}><DOMClass x={3} y={4} /><DOMClass x={5} y={6} /></DOMSFC>

// Should fail, no dom elements
const _brokenTree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>
~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
!!! error TS2605: Property 'render' is missing in type 'Element'.
~~~~~~~~~~~
!!! error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ children?: Element[]; }'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type 'dom.JSX.Element[]' is not assignable to type 'predom.JSX.Element[]'.
!!! error TS2322: Type 'dom.JSX.Element' is not assignable to type 'predom.JSX.Element'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
!!! error TS2605: Property '__domBrand' is missing in type 'MyClass'.
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.

// Should fail, nondom isn't allowed as children of dom
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>
~~~~~~~~~~~
!!! error TS2322: Type '{ children: Element[]; x: number; y: number; }' is not assignable to type '{ x: number; y: number; children?: Element[]; }'.
!!! error TS2322: Types of property 'children' are incompatible.
!!! error TS2322: Type 'predom.JSX.Element[]' is not assignable to type 'dom.JSX.Element[]'.
!!! error TS2322: Type 'predom.JSX.Element' is not assignable to type 'dom.JSX.Element'.
!!! error TS2322: Property '__domBrand' is missing in type 'Element'.

164 changes: 164 additions & 0 deletions tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
//// [tests/cases/conformance/jsx/inline/inlineJsxFactoryDeclarationsLocalTypes.tsx] ////

//// [renderer.d.ts]
export namespace dom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__domBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function dom(): dom.JSX.Element;
//// [renderer2.d.ts]
export namespace predom {
namespace JSX {
interface IntrinsicElements {
[e: string]: {};
}
interface Element {
__predomBrand: void;
props: {
children?: Element[];
};
}
interface ElementClass extends Element {
render(): Element;
}
interface ElementAttributesProperty { props: any; }
interface ElementChildrenAttribute { children: any; }
}
}
export function predom(): predom.JSX.Element;
//// [component.tsx]
/** @jsx predom */
import { predom } from "./renderer2"

export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;

export class MyClass implements predom.JSX.Element {
__predomBrand!: void;
constructor(public props: {x: number, y: number, children?: predom.JSX.Element[]}) {}
render() {
return <p>
{this.props.x} + {this.props.y} = {this.props.x + this.props.y}
{...this.props.children}
</p>;
}
}
export const tree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

export default <h></h>
//// [index.tsx]
/** @jsx dom */
import { dom } from "./renderer"
import prerendered, {MySFC, MyClass, tree} from "./component";
let elem = prerendered;
elem = <h></h>; // Expect assignability error here

const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;

class DOMClass implements dom.JSX.Element {
__domBrand!: void;
constructor(public props: {x: number, y: number, children?: dom.JSX.Element[]}) {}
render() {
return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
}
}

// Should work, everything is a DOM element
const _tree = <DOMSFC x={1} y={2}><DOMClass x={3} y={4} /><DOMClass x={5} y={6} /></DOMSFC>

// Should fail, no dom elements
const _brokenTree = <MySFC x={1} y={2}><MyClass x={3} y={4} /><MyClass x={5} y={6} /></MySFC>

// Should fail, nondom isn't allowed as children of dom
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>


//// [component.js]
"use strict";
var _this = this;
exports.__esModule = true;
/** @jsx predom */
var renderer2_1 = require("./renderer2");
exports.MySFC = function (props) { return renderer2_1.predom("p", null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y,
_this.props.children); };
var MyClass = /** @class */ (function () {
function MyClass(props) {
this.props = props;
}
MyClass.prototype.render = function () {
return renderer2_1.predom("p", null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y,
this.props.children);
};
return MyClass;
}());
exports.MyClass = MyClass;
exports.tree = renderer2_1.predom(exports.MySFC, { x: 1, y: 2 },
renderer2_1.predom(MyClass, { x: 3, y: 4 }),
renderer2_1.predom(MyClass, { x: 5, y: 6 }));
exports["default"] = renderer2_1.predom("h", null);
//// [index.js]
"use strict";
exports.__esModule = true;
/** @jsx dom */
var renderer_1 = require("./renderer");
var component_1 = require("./component");
var elem = component_1["default"];
elem = renderer_1.dom("h", null); // Expect assignability error here
var DOMSFC = function (props) { return renderer_1.dom("p", null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y,
props.children); };
var DOMClass = /** @class */ (function () {
function DOMClass(props) {
this.props = props;
}
DOMClass.prototype.render = function () {
return renderer_1.dom("p", null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y,
this.props.children);
};
return DOMClass;
}());
// Should work, everything is a DOM element
var _tree = renderer_1.dom(DOMSFC, { x: 1, y: 2 },
renderer_1.dom(DOMClass, { x: 3, y: 4 }),
renderer_1.dom(DOMClass, { x: 5, y: 6 }));
// Should fail, no dom elements
var _brokenTree = renderer_1.dom(component_1.MySFC, { x: 1, y: 2 },
renderer_1.dom(component_1.MyClass, { x: 3, y: 4 }),
renderer_1.dom(component_1.MyClass, { x: 5, y: 6 }));
// Should fail, nondom isn't allowed as children of dom
var _brokenTree2 = renderer_1.dom(DOMSFC, { x: 1, y: 2 },
component_1.tree,
component_1.tree);
Loading

0 comments on commit 488397f

Please sign in to comment.