The aim of this proposal is to add some immutability and pure checking into the typescript compiler. The proposal adds two new keywords that would give developers a means to define functions that are pure - meaning that the function has no-side effects, and define variables that are immutable - meaning that they can never be used in an impure context.
The keyword should be not be emitted into compiled javascript code.
With this proposal, the base javascript typings could be updated to support it.
I.e. the array interface would become:
interface Array<T> {
pure toString(): string;
pure toLocaleString(): string;
pure concat(...items: T[][]): T[];
pure concat(...items: (T | T[])[]): T[];
pure join(separator?: string): string;
pure indexOf(searchElement: T, fromIndex?: number): number;
pure lastIndexOf(searchElement: T, fromIndex?: number): number;
pure every(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean): boolean;
pure every(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
pure every<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
pure some(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean): boolean;
pure some(callbackfn: (this: void, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
pure some<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
pure forEach(callbackfn: (this: void, value: T, index: number, array: T[]) => void): void;
pure forEach(callbackfn: (this: void, value: T, index: number, array: T[]) => void, thisArg: undefined): void;
pure forEach<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => void, thisArg: Z): void;
pure map<U>(this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U, U];
pure map<U>(this: [T, T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U];
pure map<Z, U>(this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U];
pure map<U>(this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U, U];
pure map<U>(this: [T, T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U];
pure map<Z, U>(this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U];
pure map<U>(this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U, U];
pure map<U>(this: [T, T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U];
pure map<Z, U>(this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U];
pure map<U>(this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U): [U, U];
pure map<U>(this: [T, T], callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U];
pure map<Z, U>(this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U];
pure map<U>(callbackfn: (this: void, value: T, index: number, array: T[]) => U): U[];
pure map<U>(callbackfn: (this: void, value: T, index: number, array: T[]) => U, thisArg: undefined): U[];
pure map<Z, U>(callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[];
pure filter(callbackfn: (this: void, value: T, index: number, array: T[]) => any): T[];
pure filter(callbackfn: (this: void, value: T, index: number, array: T[]) => any, thisArg: undefined): T[];
pure filter<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => any, thisArg: Z): T[];
pure reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
pure reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
pure reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
pure reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
push(...items: T[]): number;
pop(): T | undefined;
reverse(): T[];
shift(): T | undefined;
slice(start?: number, end?: number): T[];
sort(compareFn?: (a: T, b: T) => number): this;
splice(start: number, deleteCount?: number): T[];
splice(start: number, deleteCount: number, ...items: T[]): T[];
unshift(...items: T[]): number;
[n: number]: T;
}
The aim of this proposal is to add some immutability and pure checking into the typescript compiler. The proposal adds two new keywords that would give developers a means to define functions that are pure - meaning that the function has no-side effects, and define variables that are immutable - meaning that they can never be used in an impure context.
Pure
The
purekeyword is used to define a function with no side-effects (it is allowed in the same places as theasynckeyword).The keyword should be not be emitted into compiled javascript code.
A pure function:
this.nonPure(),arg.nonPure(),nonPure(arg), andnonPure(this)are all disallowed.arg.x = 1is disallowed within the function body.thisthis.y = 1is disallowed within the function body.Immutable
Similarly a variable may be tagged as immutable:
immutable x = [](maybe keyword should be shortened toimmut, or thepurekeyword could be reused for consistency?).This keyword is replaced with
constin emitted code.An immutable variable:
const(i.e. its reference may not be reassigned).x.nonPure()is disallowed.nonPure(x)is disallowed.const y = x;is disallowed.const y = { z: x }is disallowed.x.foo = 1is disallowed.pureFn(x)is allowed.x.toString()is allowed.With objects/interfaces
The keyword(s) should also be allowed in
object(and by extensioninterface) definitions:With existing typings
With this proposal, the base javascript typings could be updated to support it.
I.e. the array interface would become: