Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New --enforceReadonly compiler option to enforce read-only semantics in type relations #58296

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
116 changes: 73 additions & 43 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/compiler/commandLineParser.ts
Expand Up @@ -1012,6 +1012,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
description: Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type,
defaultValueDescription: false,
},
{
name: "enforceReadonly",
type: "boolean",
affectsSemanticDiagnostics: true,
affectsBuildInfo: true,
category: Diagnostics.Type_Checking,
description: Diagnostics.Ensure_that_readonly_properties_remain_read_only_in_type_relationships,
defaultValueDescription: false,
},

// Module Resolution
{
Expand Down
12 changes: 12 additions & 0 deletions src/compiler/diagnosticMessages.json
Expand Up @@ -4344,6 +4344,14 @@
"category": "Error",
"code": 4126
},
"Property '{0}' is 'readonly' in the source but not in the target.": {
"category": "Error",
"code": 4127
},
"'{0}' index signature is 'readonly' in the source but not in the target.": {
"category": "Error",
"code": 4128
},

"The current host does not support the '{0}' option.": {
"category": "Error",
Expand Down Expand Up @@ -6379,6 +6387,10 @@
"category": "Message",
"code": 6719
},
"Ensure that 'readonly' properties remain read-only in type relationships.": {
"category": "Message",
"code": 6720
},

"Default catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/types.ts
Expand Up @@ -1708,7 +1708,7 @@ export interface AutoGenerateInfo {

/** @internal */
export interface GeneratedIdentifier extends Identifier {
readonly emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; };
emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; };
}

export interface QualifiedName extends Node, FlowContainer {
Expand Down Expand Up @@ -1787,7 +1787,7 @@ export interface PrivateIdentifier extends PrimaryExpression {

/** @internal */
export interface GeneratedPrivateIdentifier extends PrivateIdentifier {
readonly emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; };
emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; };
}

/** @internal */
Expand Down Expand Up @@ -7238,6 +7238,7 @@ export interface CompilerOptions {
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
enforceReadonly?: boolean;
exactOptionalPropertyTypes?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
Expand Down
14 changes: 7 additions & 7 deletions src/lib/dom.generated.d.ts
Expand Up @@ -1275,8 +1275,8 @@ interface PushSubscriptionOptionsInit {
}

interface QueuingStrategy<T = any> {
highWaterMark?: number;
size?: QueuingStrategySize<T>;
readonly highWaterMark?: number;
readonly size?: QueuingStrategySize<T>;
}

interface QueuingStrategyInit {
Expand All @@ -1285,7 +1285,7 @@ interface QueuingStrategyInit {
*
* Note that the provided high water mark will not be validated ahead of time. Instead, if it is negative, NaN, or not a number, the resulting ByteLengthQueuingStrategy will cause the corresponding stream constructor to throw.
*/
highWaterMark: number;
readonly highWaterMark: number;
}

interface RTCAnswerOptions extends RTCOfferAnswerOptions {
Expand Down Expand Up @@ -6041,9 +6041,9 @@ interface DOMException extends Error {
*/
readonly code: number;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/message) */
readonly message: string;
message: string;
/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/name) */
readonly name: string;
name: string;
readonly INDEX_SIZE_ERR: 1;
readonly DOMSTRING_SIZE_ERR: 2;
readonly HIERARCHY_REQUEST_ERR: 3;
Expand Down Expand Up @@ -18793,7 +18793,7 @@ interface ReadableStream<R = any> {

declare var ReadableStream: {
prototype: ReadableStream;
new(underlyingSource: UnderlyingByteSource, strategy?: { highWaterMark?: number }): ReadableStream<Uint8Array>;
new(underlyingSource: UnderlyingByteSource, strategy?: { readonly highWaterMark?: number }): ReadableStream<Uint8Array>;
new<R = any>(underlyingSource: UnderlyingDefaultSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
new<R = any>(underlyingSource?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
};
Expand Down Expand Up @@ -19533,7 +19533,7 @@ interface SVGElementEventMap extends ElementEventMap, GlobalEventHandlersEventMa
*/
interface SVGElement extends Element, ElementCSSInlineStyle, GlobalEventHandlers, HTMLOrSVGElement {
/** @deprecated */
readonly className: any;
className: any;
readonly ownerSVGElement: SVGSVGElement | null;
readonly viewportElement: SVGElement | null;
addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/es2015.collection.d.ts
Expand Up @@ -30,7 +30,7 @@ interface Map<K, V> {
interface MapConstructor {
new (): Map<any, any>;
new <K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
readonly prototype: Map<any, any>;
prototype: Map<any, any>;
}
declare var Map: MapConstructor;

Expand Down Expand Up @@ -64,7 +64,7 @@ interface WeakMap<K extends WeakKey, V> {

interface WeakMapConstructor {
new <K extends WeakKey = WeakKey, V = any>(entries?: readonly (readonly [K, V])[] | null): WeakMap<K, V>;
readonly prototype: WeakMap<WeakKey, any>;
prototype: WeakMap<WeakKey, any>;
}
declare var WeakMap: WeakMapConstructor;

Expand Down Expand Up @@ -96,7 +96,7 @@ interface Set<T> {

interface SetConstructor {
new <T = any>(values?: readonly T[] | null): Set<T>;
readonly prototype: Set<any>;
prototype: Set<any>;
}
declare var Set: SetConstructor;

Expand Down Expand Up @@ -124,6 +124,6 @@ interface WeakSet<T extends WeakKey> {

interface WeakSetConstructor {
new <T extends WeakKey = WeakKey>(values?: readonly T[] | null): WeakSet<T>;
readonly prototype: WeakSet<WeakKey>;
prototype: WeakSet<WeakKey>;
}
declare var WeakSet: WeakSetConstructor;
4 changes: 2 additions & 2 deletions src/lib/es2015.generator.d.ts
Expand Up @@ -30,7 +30,7 @@ interface GeneratorFunction {
/**
* A reference to the prototype.
*/
readonly prototype: Generator;
prototype: Generator;
}

interface GeneratorFunctionConstructor {
Expand All @@ -55,5 +55,5 @@ interface GeneratorFunctionConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: GeneratorFunction;
prototype: GeneratorFunction;
}
2 changes: 1 addition & 1 deletion src/lib/es2015.promise.d.ts
Expand Up @@ -2,7 +2,7 @@ interface PromiseConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Promise<any>;
prototype: Promise<any>;

/**
* Creates a new Promise.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es2015.symbol.d.ts
Expand Up @@ -2,7 +2,7 @@ interface SymbolConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Symbol;
prototype: Symbol;

/**
* Returns a new unique Symbol value.
Expand Down
4 changes: 2 additions & 2 deletions src/lib/es2017.object.d.ts
Expand Up @@ -3,7 +3,7 @@ interface ObjectConstructor {
* Returns an array of values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
values<T>(o: { [s: string]: T; } | ArrayLike<T>): T[];
values<T>(o: { readonly [s: string]: T; } | ArrayLike<T>): T[];

/**
* Returns an array of values of the enumerable properties of an object
Expand All @@ -15,7 +15,7 @@ interface ObjectConstructor {
* Returns an array of key/values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries<T>(o: { [s: string]: T; } | ArrayLike<T>): [string, T][];
entries<T>(o: { readonly [s: string]: T; } | ArrayLike<T>): [string, T][];

/**
* Returns an array of key/values of the enumerable properties of an object
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es2017.sharedmemory.d.ts
Expand Up @@ -16,7 +16,7 @@ interface SharedArrayBuffer {
}

interface SharedArrayBufferConstructor {
readonly prototype: SharedArrayBuffer;
prototype: SharedArrayBuffer;
new (byteLength: number): SharedArrayBuffer;
}
declare var SharedArrayBuffer: SharedArrayBufferConstructor;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/es2018.asyncgenerator.d.ts
Expand Up @@ -30,7 +30,7 @@ interface AsyncGeneratorFunction {
/**
* A reference to the prototype.
*/
readonly prototype: AsyncGenerator;
prototype: AsyncGenerator;
}

interface AsyncGeneratorFunctionConstructor {
Expand All @@ -55,5 +55,5 @@ interface AsyncGeneratorFunctionConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: AsyncGeneratorFunction;
prototype: AsyncGeneratorFunction;
}
2 changes: 1 addition & 1 deletion src/lib/es2018.intl.d.ts
Expand Up @@ -32,7 +32,7 @@ declare namespace Intl {
interface PluralRulesConstructor {
new (locales?: string | readonly string[], options?: PluralRulesOptions): PluralRules;
(locales?: string | readonly string[], options?: PluralRulesOptions): PluralRules;
supportedLocalesOf(locales: string | readonly string[], options?: { localeMatcher?: "lookup" | "best fit"; }): string[];
supportedLocalesOf(locales: string | readonly string[], options?: { readonly localeMatcher?: "lookup" | "best fit"; }): string[];
}

const PluralRules: PluralRulesConstructor;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/es2020.bigint.d.ts
Expand Up @@ -104,7 +104,7 @@ interface BigInt {

interface BigIntConstructor {
(value: bigint | boolean | number | string): bigint;
readonly prototype: BigInt;
prototype: BigInt;

/**
* Interprets the low bits of a BigInt as a 2's-complement signed integer.
Expand Down Expand Up @@ -370,7 +370,7 @@ interface BigInt64Array {
}

interface BigInt64ArrayConstructor {
readonly prototype: BigInt64Array;
prototype: BigInt64Array;
new (length?: number): BigInt64Array;
new (array: Iterable<bigint>): BigInt64Array;
new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigInt64Array;
Expand Down Expand Up @@ -642,7 +642,7 @@ interface BigUint64Array {
}

interface BigUint64ArrayConstructor {
readonly prototype: BigUint64Array;
prototype: BigUint64Array;
new (length?: number): BigUint64Array;
new (array: Iterable<bigint>): BigUint64Array;
new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): BigUint64Array;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es2020.intl.d.ts
Expand Up @@ -426,7 +426,7 @@ declare namespace Intl {
*
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/supportedLocalesOf).
*/
supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher; }): UnicodeBCP47LocaleIdentifier[];
supportedLocalesOf(locales?: LocalesArgument, options?: { readonly localeMatcher?: RelativeTimeFormatLocaleMatcher; }): UnicodeBCP47LocaleIdentifier[];
};

interface CollatorConstructor {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/es2021.promise.d.ts
Expand Up @@ -5,7 +5,7 @@ interface AggregateError extends Error {
interface AggregateErrorConstructor {
new (errors: Iterable<any>, message?: string): AggregateError;
(errors: Iterable<any>, message?: string): AggregateError;
readonly prototype: AggregateError;
prototype: AggregateError;
}

declare var AggregateError: AggregateErrorConstructor;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/es2021.weakref.d.ts
Expand Up @@ -10,7 +10,7 @@ interface WeakRef<T extends WeakKey> {
}

interface WeakRefConstructor {
readonly prototype: WeakRef<any>;
prototype: WeakRef<any>;

/**
* Creates a WeakRef instance for the given target value.
Expand Down Expand Up @@ -46,7 +46,7 @@ interface FinalizationRegistry<T> {
}

interface FinalizationRegistryConstructor {
readonly prototype: FinalizationRegistry<any>;
prototype: FinalizationRegistry<any>;

/**
* Creates a finalization registry with an associated cleanup callback
Expand Down