mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Instantiate generic ElementType declarations (#53943)
This commit is contained in:
parent
8749fb5c0a
commit
a177af1cc8
@ -29635,18 +29635,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function getJsxManagedAttributesFromLocatedAttributes(context: JsxOpeningLikeElement, ns: Symbol, attributesType: Type) {
|
||||
const managedSym = getJsxLibraryManagedAttributes(ns);
|
||||
if (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);
|
||||
const result = instantiateAliasOrInterfaceWithDefaults(managedSym, isInJSFile(context), ctorType, attributesType);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return attributesType;
|
||||
@ -30705,6 +30697,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return jsxNamespace && getSymbol(jsxNamespace.exports!, JsxNames.LibraryManagedAttributes, SymbolFlags.Type);
|
||||
}
|
||||
|
||||
function getJsxElementTypeSymbol(jsxNamespace: Symbol) {
|
||||
// JSX.ElementType [symbol]
|
||||
return jsxNamespace && getSymbol(jsxNamespace.exports!, JsxNames.ElementType, SymbolFlags.Type);
|
||||
}
|
||||
|
||||
/// e.g. "props" for React.d.ts,
|
||||
/// or 'undefined' if ElementAttributesProperty doesn't exist (which means all
|
||||
/// non-intrinsic elements' attributes type is 'any'),
|
||||
@ -30841,11 +30838,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getJsxElementTypeTypeAt(location: Node): Type | undefined {
|
||||
const type = getJsxType(JsxNames.ElementType, location);
|
||||
if (isErrorType(type)) return undefined;
|
||||
const ns = getJsxNamespaceAt(location);
|
||||
if (!ns) return undefined;
|
||||
const sym = getJsxElementTypeSymbol(ns);
|
||||
if (!sym) return undefined;
|
||||
const type = instantiateAliasOrInterfaceWithDefaults(sym, isInJSFile(location));
|
||||
if (!type || isErrorType(type)) return undefined;
|
||||
return type;
|
||||
}
|
||||
|
||||
function instantiateAliasOrInterfaceWithDefaults(managedSym: Symbol, inJs: boolean, ...typeArguments: Type[]) {
|
||||
const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); // fetches interface type, or initializes symbol links type parmaeters
|
||||
if (managedSym.flags & SymbolFlags.TypeAlias) {
|
||||
const params = getSymbolLinks(managedSym).typeParameters;
|
||||
if (length(params) >= typeArguments.length) {
|
||||
const args = fillMissingTypeArguments(typeArguments, params, typeArguments.length, inJs);
|
||||
return length(args) === 0 ? declaredManagedType : getTypeAliasInstantiation(managedSym, args);
|
||||
}
|
||||
}
|
||||
if (length((declaredManagedType as GenericType).typeParameters) >= typeArguments.length) {
|
||||
const args = fillMissingTypeArguments(typeArguments, (declaredManagedType as GenericType).typeParameters, typeArguments.length, inJs);
|
||||
return createTypeReference((declaredManagedType as GenericType), args);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the properties of the Jsx.IntrinsicElements interface
|
||||
*/
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx(21,9): error TS2339: Property 'ruhroh' does not exist on type 'JSX.IntrinsicElements'.
|
||||
tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx(21,10): error TS2786: 'ruhroh' cannot be used as a JSX component.
|
||||
Its type '"ruhroh"' is not a valid JSX element type.
|
||||
|
||||
|
||||
==== tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx (2 errors) ====
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
type ElementType<P = any> =
|
||||
| {
|
||||
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K]
|
||||
? K
|
||||
: never;
|
||||
}[keyof JSX.IntrinsicElements]
|
||||
| React.ComponentType<P>;
|
||||
}
|
||||
}
|
||||
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
let a = <div />;
|
||||
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
let c = <ruhroh />;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2339: Property 'ruhroh' does not exist on type 'JSX.IntrinsicElements'.
|
||||
~~~~~~
|
||||
!!! error TS2786: 'ruhroh' cannot be used as a JSX component.
|
||||
!!! error TS2786: Its type '"ruhroh"' is not a valid JSX element type.
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
//// [jsxElementTypeLiteralWithGeneric.tsx]
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
type ElementType<P = any> =
|
||||
| {
|
||||
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K]
|
||||
? K
|
||||
: never;
|
||||
}[keyof JSX.IntrinsicElements]
|
||||
| React.ComponentType<P>;
|
||||
}
|
||||
}
|
||||
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
let a = <div />;
|
||||
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
let c = <ruhroh />;
|
||||
|
||||
|
||||
//// [jsxElementTypeLiteralWithGeneric.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/// <reference path="react16.d.ts" />
|
||||
var React = require("react");
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
var a = React.createElement("div", null);
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
var c = React.createElement("ruhroh", null);
|
||||
@ -0,0 +1,50 @@
|
||||
=== tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
import * as React from "react";
|
||||
>React : Symbol(React, Decl(jsxElementTypeLiteralWithGeneric.tsx, 1, 6))
|
||||
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(jsxElementTypeLiteralWithGeneric.tsx, 1, 31))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementTypeLiteralWithGeneric.tsx, 3, 16))
|
||||
|
||||
type ElementType<P = any> =
|
||||
>ElementType : Symbol(ElementType, Decl(jsxElementTypeLiteralWithGeneric.tsx, 4, 17))
|
||||
>P : Symbol(P, Decl(jsxElementTypeLiteralWithGeneric.tsx, 5, 21))
|
||||
|
||||
| {
|
||||
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K]
|
||||
>K : Symbol(K, Decl(jsxElementTypeLiteralWithGeneric.tsx, 7, 9))
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementTypeLiteralWithGeneric.tsx, 3, 16))
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86))
|
||||
>P : Symbol(P, Decl(jsxElementTypeLiteralWithGeneric.tsx, 5, 21))
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementTypeLiteralWithGeneric.tsx, 3, 16))
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86))
|
||||
>K : Symbol(K, Decl(jsxElementTypeLiteralWithGeneric.tsx, 7, 9))
|
||||
|
||||
? K
|
||||
>K : Symbol(K, Decl(jsxElementTypeLiteralWithGeneric.tsx, 7, 9))
|
||||
|
||||
: never;
|
||||
}[keyof JSX.IntrinsicElements]
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementTypeLiteralWithGeneric.tsx, 3, 16))
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86))
|
||||
|
||||
| React.ComponentType<P>;
|
||||
>React : Symbol(React, Decl(jsxElementTypeLiteralWithGeneric.tsx, 1, 6))
|
||||
>ComponentType : Symbol(React.ComponentType, Decl(react16.d.ts, 117, 60))
|
||||
>P : Symbol(P, Decl(jsxElementTypeLiteralWithGeneric.tsx, 5, 21))
|
||||
}
|
||||
}
|
||||
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
let a = <div />;
|
||||
>a : Symbol(a, Decl(jsxElementTypeLiteralWithGeneric.tsx, 16, 3))
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
|
||||
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
let c = <ruhroh />;
|
||||
>c : Symbol(c, Decl(jsxElementTypeLiteralWithGeneric.tsx, 20, 3))
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
=== tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
import * as React from "react";
|
||||
>React : typeof React
|
||||
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
type ElementType<P = any> =
|
||||
>ElementType : ElementType<P>
|
||||
|
||||
| {
|
||||
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K]
|
||||
>JSX : any
|
||||
>JSX : any
|
||||
|
||||
? K
|
||||
: never;
|
||||
}[keyof JSX.IntrinsicElements]
|
||||
>JSX : any
|
||||
|
||||
| React.ComponentType<P>;
|
||||
>React : any
|
||||
}
|
||||
}
|
||||
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
let a = <div />;
|
||||
>a : JSX.Element
|
||||
><div /> : JSX.Element
|
||||
>div : any
|
||||
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
let c = <ruhroh />;
|
||||
>c : JSX.Element
|
||||
><ruhroh /> : JSX.Element
|
||||
>ruhroh : any
|
||||
|
||||
23
tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx
Normal file
23
tests/cases/compiler/jsxElementTypeLiteralWithGeneric.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
// @strict: true
|
||||
// @jsx: react
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
type ElementType<P = any> =
|
||||
| {
|
||||
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K]
|
||||
? K
|
||||
: never;
|
||||
}[keyof JSX.IntrinsicElements]
|
||||
| React.ComponentType<P>;
|
||||
}
|
||||
}
|
||||
|
||||
// should be fine - `ElementType` accepts `div`
|
||||
let a = <div />;
|
||||
|
||||
// Should be an error.
|
||||
// `ruhroh` is in neither `IntrinsicElements` nor `ElementType`
|
||||
let c = <ruhroh />;
|
||||
Loading…
x
Reference in New Issue
Block a user