mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Merge pull request #9167 from Microsoft/make-unions-and-intersections-of-readonly-properties-readonly
Unions and intersections of readonly properties are now also readonly
This commit is contained in:
commit
fb3f823dde
@ -4233,6 +4233,7 @@ namespace ts {
|
||||
let props: Symbol[];
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
|
||||
let isReadonly = false;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
@ -4245,6 +4246,9 @@ namespace ts {
|
||||
else if (!contains(props, prop)) {
|
||||
props.push(prop);
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
}
|
||||
else if (containingType.flags & TypeFlags.Union) {
|
||||
// A union type requires the property to be present in all constituent types
|
||||
@ -4274,6 +4278,7 @@ namespace ts {
|
||||
name);
|
||||
result.containingType = containingType;
|
||||
result.declarations = declarations;
|
||||
result.isReadonly = isReadonly;
|
||||
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
return result;
|
||||
}
|
||||
@ -12204,7 +12209,9 @@ namespace ts {
|
||||
// Variables declared with 'const'
|
||||
// Get accessors without matching set accessors
|
||||
// Enum members
|
||||
return symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0 ||
|
||||
// Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation)
|
||||
return symbol.isReadonly ||
|
||||
symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0 ||
|
||||
symbol.flags & SymbolFlags.Variable && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 ||
|
||||
symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) ||
|
||||
(symbol.flags & SymbolFlags.EnumMember) !== 0;
|
||||
|
||||
@ -2122,6 +2122,7 @@ namespace ts {
|
||||
members?: SymbolTable; // Class, interface or literal instance members
|
||||
exports?: SymbolTable; // Module exports
|
||||
globalExports?: SymbolTable; // Conditional global UMD exports
|
||||
/* @internal */ isReadonly?: boolean; // readonly? (set only for intersections and unions)
|
||||
/* @internal */ id?: number; // Unique id (used to look up SymbolLinks)
|
||||
/* @internal */ mergeId?: number; // Merge id (used to look up merged symbol)
|
||||
/* @internal */ parent?: Symbol; // Parent symbol
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts(17,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts(19,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts(21,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts(23,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts(25,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/intersection/intersectionTypeReadonly.ts (5 errors) ====
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let identical: Base & Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let mutable: Base & Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let differentType: Base & DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let differentName: Base & DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
|
||||
39
tests/baselines/reference/intersectionTypeReadonly.js
Normal file
39
tests/baselines/reference/intersectionTypeReadonly.js
Normal file
@ -0,0 +1,39 @@
|
||||
//// [intersectionTypeReadonly.ts]
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
let identical: Base & Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
let mutable: Base & Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
let differentType: Base & DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
let differentName: Base & DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
|
||||
|
||||
//// [intersectionTypeReadonly.js]
|
||||
var base;
|
||||
base.value = 12; // error, lhs can't be a readonly property
|
||||
var identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
var mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
var differentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
var differentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
45
tests/baselines/reference/unionTypeReadonly.errors.txt
Normal file
45
tests/baselines/reference/unionTypeReadonly.errors.txt
Normal file
@ -0,0 +1,45 @@
|
||||
tests/cases/conformance/types/union/unionTypeReadonly.ts(17,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/union/unionTypeReadonly.ts(19,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/union/unionTypeReadonly.ts(21,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/union/unionTypeReadonly.ts(23,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
tests/cases/conformance/types/union/unionTypeReadonly.ts(25,15): error TS2339: Property 'value' does not exist on type 'Base | DifferentName'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/union/unionTypeReadonly.ts (5 errors) ====
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let identical: Base | Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let mutable: Base | Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let differentType: Base | DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
|
||||
let differentName: Base | DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
~~~~~
|
||||
!!! error TS2339: Property 'value' does not exist on type 'Base | DifferentName'.
|
||||
|
||||
|
||||
40
tests/baselines/reference/unionTypeReadonly.js
Normal file
40
tests/baselines/reference/unionTypeReadonly.js
Normal file
@ -0,0 +1,40 @@
|
||||
//// [unionTypeReadonly.ts]
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
let identical: Base | Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
let mutable: Base | Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
let differentType: Base | DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
let differentName: Base | DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
|
||||
|
||||
|
||||
//// [unionTypeReadonly.js]
|
||||
var base;
|
||||
base.value = 12; // error, lhs can't be a readonly property
|
||||
var identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
var mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
var differentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
var differentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
@ -0,0 +1,25 @@
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
let identical: Base & Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
let mutable: Base & Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
let differentType: Base & DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
let differentName: Base & DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
26
tests/cases/conformance/types/union/unionTypeReadonly.ts
Normal file
26
tests/cases/conformance/types/union/unionTypeReadonly.ts
Normal file
@ -0,0 +1,26 @@
|
||||
interface Base {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Identical {
|
||||
readonly value: number;
|
||||
}
|
||||
interface Mutable {
|
||||
value: number;
|
||||
}
|
||||
interface DifferentType {
|
||||
readonly value: string;
|
||||
}
|
||||
interface DifferentName {
|
||||
readonly other: number;
|
||||
}
|
||||
let base: Base;
|
||||
base.value = 12 // error, lhs can't be a readonly property
|
||||
let identical: Base | Identical;
|
||||
identical.value = 12; // error, lhs can't be a readonly property
|
||||
let mutable: Base | Mutable;
|
||||
mutable.value = 12; // error, lhs can't be a readonly property
|
||||
let differentType: Base | DifferentType;
|
||||
differentType.value = 12; // error, lhs can't be a readonly property
|
||||
let differentName: Base | DifferentName;
|
||||
differentName.value = 12; // error, property 'value' doesn't exist
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user