mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Allow intersections of readonlys to be assignable to a readonly intersection (#28218)
* Allow intersections of readonlys to be assignable to a readonly intersection * Add real motivating react example to test suite
This commit is contained in:
@@ -12036,13 +12036,15 @@ namespace ts {
|
||||
return Ternary.True;
|
||||
}
|
||||
// A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X.
|
||||
if (!isGenericMappedType(source) && getConstraintTypeFromMappedType(target) === getIndexType(source)) {
|
||||
if (!isGenericMappedType(source) && isRelatedTo(getConstraintTypeFromMappedType(target), getIndexType(source))) {
|
||||
const indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target));
|
||||
const templateType = getTemplateTypeFromMappedType(target);
|
||||
if (result = isRelatedTo(indexedAccessType, templateType, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
originalErrorInfo = errorInfo;
|
||||
errorInfo = saveErrorInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//// [homomorphicMappedTypeIntersectionAssignability.ts]
|
||||
function f<TType>(
|
||||
a: { weak?: string } & Readonly<TType> & { name: "ok" },
|
||||
b: Readonly<TType & { name: string }>,
|
||||
c: Readonly<TType> & { name: string }) {
|
||||
c = a; // Works
|
||||
b = a; // Should also work
|
||||
}
|
||||
|
||||
|
||||
//// [homomorphicMappedTypeIntersectionAssignability.js]
|
||||
"use strict";
|
||||
function f(a, b, c) {
|
||||
c = a; // Works
|
||||
b = a; // Should also work
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
=== tests/cases/compiler/homomorphicMappedTypeIntersectionAssignability.ts ===
|
||||
function f<TType>(
|
||||
>f : Symbol(f, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 0))
|
||||
>TType : Symbol(TType, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 11))
|
||||
|
||||
a: { weak?: string } & Readonly<TType> & { name: "ok" },
|
||||
>a : Symbol(a, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 18))
|
||||
>weak : Symbol(weak, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 1, 8))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
|
||||
>TType : Symbol(TType, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 11))
|
||||
>name : Symbol(name, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 1, 46))
|
||||
|
||||
b: Readonly<TType & { name: string }>,
|
||||
>b : Symbol(b, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 1, 60))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
|
||||
>TType : Symbol(TType, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 11))
|
||||
>name : Symbol(name, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 2, 25))
|
||||
|
||||
c: Readonly<TType> & { name: string }) {
|
||||
>c : Symbol(c, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 2, 42))
|
||||
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
|
||||
>TType : Symbol(TType, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 11))
|
||||
>name : Symbol(name, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 3, 26))
|
||||
|
||||
c = a; // Works
|
||||
>c : Symbol(c, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 2, 42))
|
||||
>a : Symbol(a, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 18))
|
||||
|
||||
b = a; // Should also work
|
||||
>b : Symbol(b, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 1, 60))
|
||||
>a : Symbol(a, Decl(homomorphicMappedTypeIntersectionAssignability.ts, 0, 18))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
=== tests/cases/compiler/homomorphicMappedTypeIntersectionAssignability.ts ===
|
||||
function f<TType>(
|
||||
>f : <TType>(a: { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }, b: Readonly<TType & { name: string; }>, c: Readonly<TType> & { name: string; }) => void
|
||||
|
||||
a: { weak?: string } & Readonly<TType> & { name: "ok" },
|
||||
>a : { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }
|
||||
>weak : string | undefined
|
||||
>name : "ok"
|
||||
|
||||
b: Readonly<TType & { name: string }>,
|
||||
>b : Readonly<TType & { name: string; }>
|
||||
>name : string
|
||||
|
||||
c: Readonly<TType> & { name: string }) {
|
||||
>c : Readonly<TType> & { name: string; }
|
||||
>name : string
|
||||
|
||||
c = a; // Works
|
||||
>c = a : { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }
|
||||
>c : Readonly<TType> & { name: string; }
|
||||
>a : { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }
|
||||
|
||||
b = a; // Should also work
|
||||
>b = a : { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }
|
||||
>b : Readonly<TType & { name: string; }>
|
||||
>a : { weak?: string | undefined; } & Readonly<TType> & { name: "ok"; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//// [reactReadonlyHOCAssignabilityReal.tsx]
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
function myHigherOrderComponent<P>(Inner: React.ComponentClass<P & {name: string}>): React.ComponentClass<P> {
|
||||
return class OuterComponent extends React.Component<P> {
|
||||
render() {
|
||||
return <Inner {...this.props} name="Matt"/>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//// [reactReadonlyHOCAssignabilityReal.js]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
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 extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
exports.__esModule = true;
|
||||
/// <reference path="react16.d.ts" />
|
||||
var React = require("react");
|
||||
function myHigherOrderComponent(Inner) {
|
||||
return /** @class */ (function (_super) {
|
||||
__extends(OuterComponent, _super);
|
||||
function OuterComponent() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
OuterComponent.prototype.render = function () {
|
||||
return React.createElement(Inner, __assign({}, this.props, { name: "Matt" }));
|
||||
};
|
||||
return OuterComponent;
|
||||
}(React.Component));
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
=== tests/cases/compiler/reactReadonlyHOCAssignabilityReal.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
import * as React from "react";
|
||||
>React : Symbol(React, Decl(reactReadonlyHOCAssignabilityReal.tsx, 1, 6))
|
||||
|
||||
function myHigherOrderComponent<P>(Inner: React.ComponentClass<P & {name: string}>): React.ComponentClass<P> {
|
||||
>myHigherOrderComponent : Symbol(myHigherOrderComponent, Decl(reactReadonlyHOCAssignabilityReal.tsx, 1, 31))
|
||||
>P : Symbol(P, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 32))
|
||||
>Inner : Symbol(Inner, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 35))
|
||||
>React : Symbol(React, Decl(reactReadonlyHOCAssignabilityReal.tsx, 1, 6))
|
||||
>ComponentClass : Symbol(React.ComponentClass, Decl(react16.d.ts, 421, 9))
|
||||
>P : Symbol(P, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 32))
|
||||
>name : Symbol(name, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 68))
|
||||
>React : Symbol(React, Decl(reactReadonlyHOCAssignabilityReal.tsx, 1, 6))
|
||||
>ComponentClass : Symbol(React.ComponentClass, Decl(react16.d.ts, 421, 9))
|
||||
>P : Symbol(P, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 32))
|
||||
|
||||
return class OuterComponent extends React.Component<P> {
|
||||
>OuterComponent : Symbol(OuterComponent, Decl(reactReadonlyHOCAssignabilityReal.tsx, 4, 10))
|
||||
>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
|
||||
>React : Symbol(React, Decl(reactReadonlyHOCAssignabilityReal.tsx, 1, 6))
|
||||
>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
|
||||
>P : Symbol(P, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 32))
|
||||
|
||||
render() {
|
||||
>render : Symbol(OuterComponent.render, Decl(reactReadonlyHOCAssignabilityReal.tsx, 4, 60))
|
||||
|
||||
return <Inner {...this.props} name="Matt"/>;
|
||||
>Inner : Symbol(Inner, Decl(reactReadonlyHOCAssignabilityReal.tsx, 3, 35))
|
||||
>this.props : Symbol(React.Component.props, Decl(react16.d.ts, 367, 32))
|
||||
>this : Symbol(OuterComponent, Decl(reactReadonlyHOCAssignabilityReal.tsx, 4, 10))
|
||||
>props : Symbol(React.Component.props, Decl(react16.d.ts, 367, 32))
|
||||
>name : Symbol(name, Decl(reactReadonlyHOCAssignabilityReal.tsx, 6, 41))
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
=== tests/cases/compiler/reactReadonlyHOCAssignabilityReal.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
import * as React from "react";
|
||||
>React : typeof React
|
||||
|
||||
function myHigherOrderComponent<P>(Inner: React.ComponentClass<P & {name: string}>): React.ComponentClass<P> {
|
||||
>myHigherOrderComponent : <P>(Inner: React.ComponentClass<P & { name: string; }, any>) => React.ComponentClass<P, any>
|
||||
>Inner : React.ComponentClass<P & { name: string; }, any>
|
||||
>React : any
|
||||
>name : string
|
||||
>React : any
|
||||
|
||||
return class OuterComponent extends React.Component<P> {
|
||||
>class OuterComponent extends React.Component<P> { render() { return <Inner {...this.props} name="Matt"/>; } } : typeof OuterComponent
|
||||
>OuterComponent : typeof OuterComponent
|
||||
>React.Component : React.Component<P, {}, any>
|
||||
>React : typeof React
|
||||
>Component : typeof React.Component
|
||||
|
||||
render() {
|
||||
>render : () => JSX.Element
|
||||
|
||||
return <Inner {...this.props} name="Matt"/>;
|
||||
><Inner {...this.props} name="Matt"/> : JSX.Element
|
||||
>Inner : React.ComponentClass<P & { name: string; }, any>
|
||||
>this.props : Readonly<{ children?: React.ReactNode; }> & Readonly<P>
|
||||
>this : this
|
||||
>props : Readonly<{ children?: React.ReactNode; }> & Readonly<P>
|
||||
>name : "Matt"
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// @strict: true
|
||||
function f<TType>(
|
||||
a: { weak?: string } & Readonly<TType> & { name: "ok" },
|
||||
b: Readonly<TType & { name: string }>,
|
||||
c: Readonly<TType> & { name: string }) {
|
||||
c = a; // Works
|
||||
b = a; // Should also work
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// @strict: true
|
||||
// @jsx: react
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
function myHigherOrderComponent<P>(Inner: React.ComponentClass<P & {name: string}>): React.ComponentClass<P> {
|
||||
return class OuterComponent extends React.Component<P> {
|
||||
render() {
|
||||
return <Inner {...this.props} name="Matt"/>;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user