diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fe63d0c1c3b..2831a591fbc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4197,6 +4197,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) { @@ -4209,6 +4210,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 @@ -4238,6 +4242,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; } @@ -11975,11 +11980,9 @@ namespace ts { // Variables declared with 'const' // Get accessors without matching set accessors // Enum members - // Unions and intersections of the above - if (symbol.flags & SymbolFlags.SyntheticProperty) { - return forEach(symbol.declarations, decl => isReadonlySymbol(getSymbolOfNode(decl))); - } - 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; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index db34bb7c6e8..7487d1db258 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2104,6 +2104,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