From ab32fcadbdc30c8b0c72236579f37ce70b3048a9 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 15 Jan 2021 17:23:01 -0800 Subject: [PATCH] Fix type parameter lookup for TypeAlias LibraryManagedAttributes (#42245) --- src/compiler/checker.ts | 13 ++-- ...sxLibraryManagedAttributesUnusedGeneric.js | 34 +++++++++ ...raryManagedAttributesUnusedGeneric.symbols | 70 +++++++++++++++++++ ...ibraryManagedAttributesUnusedGeneric.types | 51 ++++++++++++++ ...xLibraryManagedAttributesUnusedGeneric.tsx | 30 ++++++++ 5 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.js create mode 100644 tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.symbols create mode 100644 tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.types create mode 100644 tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 70bd5d08ebf..6875be4f893 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24771,16 +24771,19 @@ namespace ts { function getJsxManagedAttributesFromLocatedAttributes(context: JsxOpeningLikeElement, ns: Symbol, attributesType: Type) { const managedSym = getJsxLibraryManagedAttributes(ns); if (managedSym) { - const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); + const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); // fetches interface type, or initializes symbol links type parmaeters const ctorType = getStaticTypeOfReferencedJsxConstructor(context); + if (managedSym.flags & SymbolFlags.TypeAlias) { + const params = getSymbolLinks(managedSym).typeParameters; + if (length(params) >= 2) { + const args = fillMissingTypeArguments([ctorType, attributesType], params, 2, isInJSFile(context)); + return getTypeAliasInstantiation(managedSym, args); + } + } if (length((declaredManagedType as GenericType).typeParameters) >= 2) { const args = fillMissingTypeArguments([ctorType, attributesType], (declaredManagedType as GenericType).typeParameters, 2, isInJSFile(context)); return createTypeReference((declaredManagedType as GenericType), args); } - else if (length(declaredManagedType.aliasTypeArguments) >= 2) { - const args = fillMissingTypeArguments([ctorType, attributesType], declaredManagedType.aliasTypeArguments, 2, isInJSFile(context)); - return getTypeAliasInstantiation(declaredManagedType.aliasSymbol!, args); - } } return attributesType; } diff --git a/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.js b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.js new file mode 100644 index 00000000000..d994e109fec --- /dev/null +++ b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.js @@ -0,0 +1,34 @@ +//// [jsxLibraryManagedAttributesUnusedGeneric.tsx] +// @ts-ignore +import React from 'react' + +declare const jsx: typeof React.createElement +namespace jsx { + export namespace JSX { + export interface Element {} + export interface ElementClass {} + export interface ElementAttributesProperty {} + export interface ElementChildrenAttribute {} + export interface IntrinsicAttributes {} + export interface IntrinsicClassAttributes {} + export type IntrinsicElements = { + div: { className: string } + } + // Works + // export type LibraryManagedAttributes = P & { css: string }; + + // Equivalent to above, but fails + export type WithCSSProp

= P & { css: string } + export type LibraryManagedAttributes = WithCSSProp

+ + } +} + +declare const Comp: (p: { className?: string }) => null + +; + +//// [jsxLibraryManagedAttributesUnusedGeneric.js] +"use strict"; +exports.__esModule = true; +jsx(Comp, { css: "color:hotpink;" }); diff --git a/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.symbols b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.symbols new file mode 100644 index 00000000000..648be8bafae --- /dev/null +++ b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.symbols @@ -0,0 +1,70 @@ +=== tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx === +// @ts-ignore +import React from 'react' +>React : Symbol(React, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 1, 6)) + +declare const jsx: typeof React.createElement +>jsx : Symbol(jsx, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 3, 13), Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 3, 45)) +>React : Symbol(React, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 1, 6)) + +namespace jsx { +>jsx : Symbol(jsx, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 3, 13), Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 3, 45)) + + export namespace JSX { +>JSX : Symbol(JSX, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 4, 15)) + + export interface Element {} +>Element : Symbol(Element, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 5, 26)) + + export interface ElementClass {} +>ElementClass : Symbol(ElementClass, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 6, 35)) + + export interface ElementAttributesProperty {} +>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 7, 40)) + + export interface ElementChildrenAttribute {} +>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 8, 53)) + + export interface IntrinsicAttributes {} +>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 9, 52)) + + export interface IntrinsicClassAttributes {} +>IntrinsicClassAttributes : Symbol(IntrinsicClassAttributes, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 10, 47)) +>T : Symbol(T, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 11, 50)) + + export type IntrinsicElements = { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 11, 55)) + + div: { className: string } +>div : Symbol(div, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 12, 41)) +>className : Symbol(className, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 13, 18)) + } + // Works + // export type LibraryManagedAttributes = P & { css: string }; + + // Equivalent to above, but fails + export type WithCSSProp

= P & { css: string } +>WithCSSProp : Symbol(WithCSSProp, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 14, 9)) +>P : Symbol(P, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 19, 32)) +>P : Symbol(P, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 19, 32)) +>css : Symbol(css, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 19, 42)) + + export type LibraryManagedAttributes = WithCSSProp

+>LibraryManagedAttributes : Symbol(LibraryManagedAttributes, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 19, 56)) +>C : Symbol(C, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 20, 45)) +>P : Symbol(P, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 20, 47)) +>WithCSSProp : Symbol(WithCSSProp, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 14, 9)) +>P : Symbol(P, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 20, 47)) + + } +} + +declare const Comp: (p: { className?: string }) => null +>Comp : Symbol(Comp, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 25, 13)) +>p : Symbol(p, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 25, 21)) +>className : Symbol(className, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 25, 25)) + +; +>Comp : Symbol(Comp, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 25, 13)) +>css : Symbol(css, Decl(jsxLibraryManagedAttributesUnusedGeneric.tsx, 27, 6)) + diff --git a/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.types b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.types new file mode 100644 index 00000000000..f47bd7afddd --- /dev/null +++ b/tests/baselines/reference/jsxLibraryManagedAttributesUnusedGeneric.types @@ -0,0 +1,51 @@ +=== tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx === +// @ts-ignore +import React from 'react' +>React : any + +declare const jsx: typeof React.createElement +>jsx : error +>React.createElement : error +>React : any +>createElement : any + +namespace jsx { + export namespace JSX { + export interface Element {} + export interface ElementClass {} + export interface ElementAttributesProperty {} + export interface ElementChildrenAttribute {} + export interface IntrinsicAttributes {} + export interface IntrinsicClassAttributes {} + export type IntrinsicElements = { +>IntrinsicElements : IntrinsicElements + + div: { className: string } +>div : { className: string; } +>className : string + } + // Works + // export type LibraryManagedAttributes = P & { css: string }; + + // Equivalent to above, but fails + export type WithCSSProp

= P & { css: string } +>WithCSSProp : WithCSSProp

+>css : string + + export type LibraryManagedAttributes = WithCSSProp

+>LibraryManagedAttributes : WithCSSProp

+ + } +} + +declare const Comp: (p: { className?: string }) => null +>Comp : (p: { className?: string;}) => null +>p : { className?: string; } +>className : string +>null : null + +; +> : jsx.JSX.Element +>Comp : (p: { className?: string; }) => null +>css : string + diff --git a/tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx b/tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx new file mode 100644 index 00000000000..6112a4151e3 --- /dev/null +++ b/tests/cases/compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx @@ -0,0 +1,30 @@ +// @jsx: react +// @jsxFactory: jsx +// @ts-ignore +import React from 'react' + +declare const jsx: typeof React.createElement +namespace jsx { + export namespace JSX { + export interface Element {} + export interface ElementClass {} + export interface ElementAttributesProperty {} + export interface ElementChildrenAttribute {} + export interface IntrinsicAttributes {} + export interface IntrinsicClassAttributes {} + export type IntrinsicElements = { + div: { className: string } + } + // Works + // export type LibraryManagedAttributes = P & { css: string }; + + // Equivalent to above, but fails + export type WithCSSProp

= P & { css: string } + export type LibraryManagedAttributes = WithCSSProp

+ + } +} + +declare const Comp: (p: { className?: string }) => null + +; \ No newline at end of file