mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Actually get the apparent type of intersection members when calculating intersection apparent types (#21133)
* Actually get the apparent type of intersection members when calculating intersection apparent types * Add nonjsx variant * Fix nit
This commit is contained in:
1 parent
9ad9dc106c
commit
99d6b0d308
10 files changed
+385
-8
No files matched your search
@@ -5416,18 +5416,19 @@ namespace ts {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type {
|
||||
function getTypeWithThisArgument(type: Type, thisArgument?: Type, needApparentType?: boolean): Type {
|
||||
if (getObjectFlags(type) & ObjectFlags.Reference) {
|
||||
const target = (<TypeReference>type).target;
|
||||
const typeArguments = (<TypeReference>type).typeArguments;
|
||||
if (length(target.typeParameters) === length(typeArguments)) {
|
||||
return createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType]));
|
||||
const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType]));
|
||||
return needApparentType ? getApparentType(ref) : ref;
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(map((<IntersectionType>type).types, t => getTypeWithThisArgument(t, thisArgument)));
|
||||
return getIntersectionType(map((<IntersectionType>type).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType)));
|
||||
}
|
||||
return type;
|
||||
return needApparentType ? getApparentType(type) : type;
|
||||
}
|
||||
|
||||
function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: TypeParameter[], typeArguments: Type[]) {
|
||||
@@ -6107,7 +6108,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getApparentTypeOfIntersectionType(type: IntersectionType) {
|
||||
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type));
|
||||
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true));
|
||||
}
|
||||
|
||||
function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined {
|
||||
@@ -14068,7 +14069,7 @@ namespace ts {
|
||||
// If the given type is an object or union type with a single signature, and if that signature has at
|
||||
// least as many parameters as the given function, return the signature. Otherwise return undefined.
|
||||
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature {
|
||||
const signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||
const signatures = getSignaturesOfType(type, SignatureKind.Call);
|
||||
if (signatures.length === 1) {
|
||||
const signature = signatures[0];
|
||||
if (!isAritySmaller(signature, node)) {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//// [intersectionOfTypeVariableHasApparentSignatures.ts]
|
||||
interface Component<P> {
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children?: (items: {x: number}) => void
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
|
||||
f({
|
||||
props: {
|
||||
children: (({ x }) => { })
|
||||
}
|
||||
});
|
||||
|
||||
//// [intersectionOfTypeVariableHasApparentSignatures.js]
|
||||
f({
|
||||
props: {
|
||||
children: (function (_a) {
|
||||
var x = _a.x;
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
=== tests/cases/compiler/intersectionOfTypeVariableHasApparentSignatures.ts ===
|
||||
interface Component<P> {
|
||||
>Component : Symbol(Component, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 0))
|
||||
>P : Symbol(P, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 20))
|
||||
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
>props : Symbol(Component.props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 24))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>P : Symbol(P, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 20))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>children : Symbol(children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 1, 35))
|
||||
}
|
||||
|
||||
interface Props {
|
||||
>Props : Symbol(Props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 2, 1))
|
||||
|
||||
children?: (items: {x: number}) => void
|
||||
>children : Symbol(Props.children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 4, 17))
|
||||
>items : Symbol(items, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 5, 16))
|
||||
>x : Symbol(x, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 5, 24))
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
>f : Symbol(f, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 6, 1))
|
||||
>T : Symbol(T, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 19))
|
||||
>Props : Symbol(Props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 2, 1))
|
||||
>i : Symbol(i, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 36))
|
||||
>Component : Symbol(Component, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 8, 19))
|
||||
|
||||
f({
|
||||
>f : Symbol(f, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 6, 1))
|
||||
|
||||
props: {
|
||||
>props : Symbol(props, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 10, 3))
|
||||
|
||||
children: (({ x }) => { })
|
||||
>children : Symbol(children, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 11, 12))
|
||||
>x : Symbol(x, Decl(intersectionOfTypeVariableHasApparentSignatures.ts, 12, 21))
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
=== tests/cases/compiler/intersectionOfTypeVariableHasApparentSignatures.ts ===
|
||||
interface Component<P> {
|
||||
>Component : Component<P>
|
||||
>P : P
|
||||
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
>props : Readonly<P> & Readonly<{ children?: {} | undefined; }>
|
||||
>Readonly : Readonly<T>
|
||||
>P : P
|
||||
>Readonly : Readonly<T>
|
||||
>children : {} | undefined
|
||||
}
|
||||
|
||||
interface Props {
|
||||
>Props : Props
|
||||
|
||||
children?: (items: {x: number}) => void
|
||||
>children : ((items: { x: number; }) => void) | undefined
|
||||
>items : { x: number; }
|
||||
>x : number
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
>f : <T extends Props>(i: Component<T>) => void
|
||||
>T : T
|
||||
>Props : Props
|
||||
>i : Component<T>
|
||||
>Component : Component<P>
|
||||
>T : T
|
||||
|
||||
f({
|
||||
>f({ props: { children: (({ x }) => { }) }}) : void
|
||||
>f : <T extends Props>(i: Component<T>) => void
|
||||
>{ props: { children: (({ x }) => { }) }} : { props: { children: ({ x }: { x: number; }) => void; }; }
|
||||
|
||||
props: {
|
||||
>props : { children: ({ x }: { x: number; }) => void; }
|
||||
>{ children: (({ x }) => { }) } : { children: ({ x }: { x: number; }) => void; }
|
||||
|
||||
children: (({ x }) => { })
|
||||
>children : ({ x }: { x: number; }) => void
|
||||
>(({ x }) => { }) : ({ x }: { x: number; }) => void
|
||||
>({ x }) => { } : ({ x }: { x: number; }) => void
|
||||
>x : number
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
//// [jsxCallbackWithDestructuring.tsx]
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
declare class Component<P, S> {
|
||||
constructor(props: P, context?: any);
|
||||
render(): {};
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface Element { }
|
||||
interface ElementClass {
|
||||
render(): {};
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
interface IntrinsicAttributes { }
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
children?: (props: { x: number }) => any;
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
|
||||
//// [jsxCallbackWithDestructuring.jsx]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
exports.__esModule = true;
|
||||
var MyComponent = /** @class */ (function (_super) {
|
||||
__extends(MyComponent, _super);
|
||||
function MyComponent() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return MyComponent;
|
||||
}(Component));
|
||||
exports.MyComponent = MyComponent;
|
||||
<MyComponent children={function (_a) {
|
||||
var x = _a.x;
|
||||
}}/>;
|
||||
@@ -0,0 +1,81 @@
|
||||
=== tests/cases/compiler/jsxCallbackWithDestructuring.tsx ===
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>S : Symbol(S, Decl(jsxCallbackWithDestructuring.tsx, 1, 27), Decl(jsxCallbackWithDestructuring.tsx, 2, 26))
|
||||
|
||||
declare class Component<P, S> {
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>S : Symbol(S, Decl(jsxCallbackWithDestructuring.tsx, 1, 27), Decl(jsxCallbackWithDestructuring.tsx, 2, 26))
|
||||
|
||||
constructor(props: P, context?: any);
|
||||
>props : Symbol(props, Decl(jsxCallbackWithDestructuring.tsx, 3, 16))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
>context : Symbol(context, Decl(jsxCallbackWithDestructuring.tsx, 3, 25))
|
||||
|
||||
render(): {};
|
||||
>render : Symbol(Component.render, Decl(jsxCallbackWithDestructuring.tsx, 3, 41))
|
||||
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
>props : Symbol(Component.props, Decl(jsxCallbackWithDestructuring.tsx, 4, 17))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>children : Symbol(children, Decl(jsxCallbackWithDestructuring.tsx, 5, 21))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
|
||||
>P : Symbol(P, Decl(jsxCallbackWithDestructuring.tsx, 1, 20), Decl(jsxCallbackWithDestructuring.tsx, 2, 24))
|
||||
}
|
||||
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(jsxCallbackWithDestructuring.tsx, 6, 1))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(jsxCallbackWithDestructuring.tsx, 8, 16))
|
||||
|
||||
interface Element { }
|
||||
>Element : Symbol(Element, Decl(jsxCallbackWithDestructuring.tsx, 9, 19))
|
||||
|
||||
interface ElementClass {
|
||||
>ElementClass : Symbol(ElementClass, Decl(jsxCallbackWithDestructuring.tsx, 10, 30))
|
||||
|
||||
render(): {};
|
||||
>render : Symbol(ElementClass.render, Decl(jsxCallbackWithDestructuring.tsx, 11, 33))
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(jsxCallbackWithDestructuring.tsx, 13, 9))
|
||||
>props : Symbol(ElementAttributesProperty.props, Decl(jsxCallbackWithDestructuring.tsx, 14, 45))
|
||||
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
>ElementChildrenAttribute : Symbol(ElementChildrenAttribute, Decl(jsxCallbackWithDestructuring.tsx, 14, 58))
|
||||
>children : Symbol(ElementChildrenAttribute.children, Decl(jsxCallbackWithDestructuring.tsx, 15, 44))
|
||||
|
||||
interface IntrinsicAttributes { }
|
||||
>IntrinsicAttributes : Symbol(IntrinsicAttributes, Decl(jsxCallbackWithDestructuring.tsx, 15, 60))
|
||||
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
>IntrinsicClassAttributes : Symbol(IntrinsicClassAttributes, Decl(jsxCallbackWithDestructuring.tsx, 16, 42))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 17, 43))
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
|
||||
children?: (props: { x: number }) => any;
|
||||
>children : Symbol(RouteProps.children, Decl(jsxCallbackWithDestructuring.tsx, 21, 29))
|
||||
>props : Symbol(props, Decl(jsxCallbackWithDestructuring.tsx, 22, 16))
|
||||
>x : Symbol(x, Decl(jsxCallbackWithDestructuring.tsx, 22, 24))
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
>MyComponent : Symbol(MyComponent, Decl(jsxCallbackWithDestructuring.tsx, 23, 1))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 24, 25))
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
>RouteProps : Symbol(RouteProps, Decl(jsxCallbackWithDestructuring.tsx, 19, 1))
|
||||
>Component : Symbol(Component, Decl(jsxCallbackWithDestructuring.tsx, 0, 0), Decl(jsxCallbackWithDestructuring.tsx, 1, 39))
|
||||
>T : Symbol(T, Decl(jsxCallbackWithDestructuring.tsx, 24, 25))
|
||||
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
>MyComponent : Symbol(MyComponent, Decl(jsxCallbackWithDestructuring.tsx, 23, 1))
|
||||
>children : Symbol(children, Decl(jsxCallbackWithDestructuring.tsx, 25, 12))
|
||||
>x : Symbol(x, Decl(jsxCallbackWithDestructuring.tsx, 25, 25))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
=== tests/cases/compiler/jsxCallbackWithDestructuring.tsx ===
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
>Component : Component<P, S>
|
||||
>P : P
|
||||
>S : S
|
||||
|
||||
declare class Component<P, S> {
|
||||
>Component : Component<P, S>
|
||||
>P : P
|
||||
>S : S
|
||||
|
||||
constructor(props: P, context?: any);
|
||||
>props : P
|
||||
>P : P
|
||||
>context : any
|
||||
|
||||
render(): {};
|
||||
>render : () => {}
|
||||
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
>props : Readonly<{ children?: {} | undefined; }> & Readonly<P>
|
||||
>Readonly : Readonly<T>
|
||||
>children : {} | undefined
|
||||
>Readonly : Readonly<T>
|
||||
>P : P
|
||||
}
|
||||
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
>JSX : any
|
||||
|
||||
interface Element { }
|
||||
>Element : Element
|
||||
|
||||
interface ElementClass {
|
||||
>ElementClass : ElementClass
|
||||
|
||||
render(): {};
|
||||
>render : () => {}
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
>ElementAttributesProperty : ElementAttributesProperty
|
||||
>props : {}
|
||||
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
>ElementChildrenAttribute : ElementChildrenAttribute
|
||||
>children : {}
|
||||
|
||||
interface IntrinsicAttributes { }
|
||||
>IntrinsicAttributes : IntrinsicAttributes
|
||||
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
>IntrinsicClassAttributes : IntrinsicClassAttributes<T>
|
||||
>T : T
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
>RouteProps : RouteProps
|
||||
|
||||
children?: (props: { x: number }) => any;
|
||||
>children : ((props: { x: number; }) => any) | undefined
|
||||
>props : { x: number; }
|
||||
>x : number
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
>MyComponent : MyComponent<T>
|
||||
>T : T
|
||||
>RouteProps : RouteProps
|
||||
>RouteProps : RouteProps
|
||||
>Component : Component<T, {}>
|
||||
>T : T
|
||||
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
><MyComponent children={({ x }) => {}}/> : JSX.Element
|
||||
>MyComponent : typeof MyComponent
|
||||
>children : ({ x }: { x: number; }) => void
|
||||
>({ x }) => {} : ({ x }: { x: number; }) => void
|
||||
>x : number
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ tests/cases/conformance/jsx/file.tsx(9,33): error TS2322: Type '{ a: number; }'
|
||||
Property 'b' is missing in type '{ a: number; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T & { ignore-prop: true; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
|
||||
Type 'T & { ignore-prop: true; }' is not assignable to type '{ b: {}; a: {}; }'.
|
||||
Property 'a' is missing in type 'T & { ignore-prop: true; }'.
|
||||
Property 'a' is missing in type '{ b: number; } & { ignore-prop: true; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
|
||||
@@ -24,5 +24,5 @@ tests/cases/conformance/jsx/file.tsx(10,33): error TS2322: Type 'T & { ignore-pr
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'T & { ignore-prop: true; }' is not assignable to type 'IntrinsicAttributes & { b: {}; a: {}; }'.
|
||||
!!! error TS2322: Type 'T & { ignore-prop: true; }' is not assignable to type '{ b: {}; a: {}; }'.
|
||||
!!! error TS2322: Property 'a' is missing in type 'T & { ignore-prop: true; }'.
|
||||
!!! error TS2322: Property 'a' is missing in type '{ b: number; } & { ignore-prop: true; }'.
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// @strictNullChecks: true
|
||||
// @noImplicitAny: true
|
||||
interface Component<P> {
|
||||
props: Readonly<P> & Readonly<{ children?: {} }>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children?: (items: {x: number}) => void
|
||||
}
|
||||
|
||||
declare function f<T extends Props>(i: Component<T>): void;
|
||||
|
||||
f({
|
||||
props: {
|
||||
children: (({ x }) => { })
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
// @jsx: preserve
|
||||
// @noImplicitAny: true
|
||||
// @strictNullChecks: true
|
||||
|
||||
|
||||
// minimal component
|
||||
interface Component<P = {}, S = {}> { }
|
||||
declare class Component<P, S> {
|
||||
constructor(props: P, context?: any);
|
||||
render(): {};
|
||||
props: Readonly<{ children?: {} }> & Readonly<P>;
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface Element { }
|
||||
interface ElementClass {
|
||||
render(): {};
|
||||
}
|
||||
interface ElementAttributesProperty { props: {}; }
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
interface IntrinsicAttributes { }
|
||||
interface IntrinsicClassAttributes<T> { }
|
||||
}
|
||||
}
|
||||
|
||||
export interface RouteProps {
|
||||
children?: (props: { x: number }) => any;
|
||||
}
|
||||
export class MyComponent<T extends RouteProps = RouteProps> extends Component<T> { }
|
||||
<MyComponent children={({ x }) => {}}/>
|
||||
Reference in new issue
Block a user