microsoft / typescript Goto Github PK
View Code? Open in Web Editor NEWTypeScript is a superset of JavaScript that compiles to clean JavaScript output.
Home Page: https://www.typescriptlang.org
License: Apache License 2.0
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
Home Page: https://www.typescriptlang.org
License: Apache License 2.0
var x = { f() { return 1; } }
var y = { f: () => { return 1; } }
var z = { f: function() { return 1; } }
Expected:
var x = { f: function () { return 1; } };
var y = { f: function () { return 1; } };
var z = { f: function () { return 1; } };
Actual:
var x = { f: function f() { return 1;} };
var y = { f: function () { return 1;} };
var z = { f: function () { return 1;} };
This would be a breaking change, but might align with ES6?
var x = 001;
Should be an error if compiled with --target ES5
interface Foo {
x: number;
}
export class Bar implements Foo {
x: number;
}
Expected: Exported class 'Bar' implements private interface 'Foo'.
Actual: no error
import require = require('collisionExportsRequireAndAlias_file1'); // Error
//!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module.
import exports = require('collisionExportsRequireAndAlias_file11'); // Error
//!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module.
Expected: errors above
Actual: no errors
See related testcases for other examples of where this is an error linked in TC ID field:
collisionExportsRequireAndClass.errors.txt
collisionExportsRequireAndEnum.errors.txt
collisionExportsRequireAndFunction.errors.txt
collisionExportsRequireAndModule.errors.txt
collisionExportsRequireAndVar.errors.txt
collisionRestParameterArrowFunctions.errors.txt
interface Foo {
x: number;
}
export class Bar {
f(): Foo { return null; }
}
Expected: Return type of public method from exported class has or is using private type 'Foo'.
Actual: no error
Allow a declarative way of adding members to an existing type's prototype
Example:
class Shape {
// ...
}
/* ...elsewhere...*/
extension class Shape { // Syntax??
getArea() { return /* ... */; }
}
var x = new Shape();
console.log(x.getArea()); // OK
When encountering code like
().toString();
We make a strange assumption, which is that the ()
belongs to an arrow function like the following:
() => x
This is weird because it bubbles up to nothing better than the error
Cannot find name 'toString'.
In this case, we should check to see if the next token is an arrow (=>
).
interface Foo { a }
interface Bar { b }
interface Object {
[n: number]: Foo;
}
interface Function {
[n: number]: Bar;
}
var o = {};
var f = () => { };
var v1: {
//!!! Cannot convert '{}' to '{ [x: number]: Foo; }':
//!!! Numeric index signature is missing in type '{}'.
[n: number]: Foo
} = o;
var v2: {
//!!! Cannot convert '() => void' to '{ [x: number]: Bar; }':
//!!! Numeric index signature is missing in type '() => void'.
[n: number]: Bar
} = f;
Expected: no errors
Actual: errors in the comments above
Verify test case:
tests/cases/compiler/augmentedTypeBracketAccessIndexSignature.ts
tests/cases/conformance/types/members/objectTypeWithCallSignatureHidingMembersOfExtendedFunction.ts
//==== tests/cases/compiler/collisionThisExpressionAndAliasInGlobal.ts (1 errors) ====
module a {
export var b = 10;
}
var f = () => this;
import _this = a; // Error
//!!! Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.
Expected: errors as above
Actual: no errors
Similar but different error:
//==== tests/cases/compiler/collisionThisExpressionAndAmbientClassInGlobal.ts (1 errors) ====
declare class _this { // no error - as no code generation
}
var f = () => this;
var a = new _this(); // Error
//!!! Expression resolves to variable declaration '_this' that compiler uses to capture 'this' reference.
Code:
module Editor {
export class Buffer {
lines: List<string>;
}
class List<T> { }
}
Expected: Error (on 'lines': List is not exported)
Actual: No error
Implement TypeScript support for the for-of
loop as described in the ES6 proposal
Reference: https://github.com/dherman/tc39-codex-wiki/blob/master/data/es6/for-of/index.md
To be determined: What cases can we support code generation for when targeting pre-ES6 targets?
Support an abstract
keyword for classes and their methods
Examples:
abstract class Base {
abstract getThing(): string;
getOtherThing() { return 'hello'; }
}
var x = new Base(); // Error, 'Base' is abstract
// Error, must either be 'abstract' or implement concrete 'getThing'
class Derived1 extends Base { }
class Derived2 extends Base {
getThing() { return 'hello'; }
foo() { super.getThing(); } // Error: cannot invoke abstract members through 'super'
}
var x = new Derived2(); // OK
var y: Base = new Derived2(); // Also OK
y.getThing(); // OK
y.getOtherThing(); // OK
abstract class Empty { } // OK
Support compiling multiple input .ts files into one external module.
Need to determine exactly how the module boundaries are defined when doing this.
Support some level of automatically generating doc comments for non-TypeScript JavaScript consumers.
Need more details on what exactly people would like to see generated.
module X.Y {
export class Point {
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
x: number;
y: number;
}
}
module X.Y {
export module Point {
export var Origin = new Point(0, 0);
}
}
Expected (old compiler):
Module 'Point' cannot merge with previous declaration of 'Point' in a different file 'class.ts'.
Actual (new compiler): no error
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-let-and-const-declarations
The only major implication here how we would treat export const x = 4;
in the context of an internal module, as this basically introduces the concept of a readonly
variable. See #12
declare module "fs" {
var x: string;
}
declare module "fs" {
var y: number;
}
Expected:
!!! Duplicate identifier ''fs''.
!!! Ambient external module declaration cannot be reopened.
Actual: no error
import Sammy = require("errorsOnImportedSymbol_0");
var x = new Sammy.Sammy(); // Sammy.Sammy does not exist
var y = Sammy.Sammy(); // Sammy.Sammy does not exist
Expected:
var Sammy = require ( "errorsOnImportedSymbol_0" ) ;
var x = new Sammy . Sammy ( ) ;
var y = Sammy . Sammy ( ) ;
Actual:
var x = new Sammy . Sammy ( ) ;
var y = Sammy . Sammy ( ) ;
with (window) {
var p = () => this;
}
Expected: no error
Actual:
with (window) {
!!! Could not find symbol 'window'.
var p = () => this;
}
The compiler should issue an error when code uses values before they could possibly be initialized.
// Error, 'Derived' declaration must be after 'Base'
class Derived extends Base { }
class Base { }
Implement TypeScript support for the proposed ES7 functionality for async functions
See http://wiki.ecmascript.org/doku.php?id=strawman:async_functions
module m1 {
export module m2 {
export function f1(c1: C1) {
}
}
class C1 { }
}
Expected: Parameter 'c1' of exported function has or is using private type 'C1'.
Actual: no error
Create a project template and project system support for a TypeScript 'library'
Library project outputs would include a .d.ts and a .js file; referencing projects would consume the .d.ts file automatically and have separate compilation. Refactoring in the referenced project would be reflected in any loaded referencing projects.
Open questions
document.all
get?C# and other languages have syntax sugar for accessing property chains where null
(or in our case, undefined
) might be encountered at any point in the object hierarchy.
var x = { y: { z: null, q: undefined } };
console.log(x?.y?.z?.foo); // Should print 'null'
console.log(x?.baz); // Still an error
console.log(x.y.q?.bar); // Should print 'undefined'
Need proposal on what exactly we should codegen, keeping in mind side effects of accessors.
Edit by @DanielRosenwasser February 27, 2018: This proposal is also called the "null propagation" operator.
tests\cases\conformance\types\typeRelationships\typeAndMemberIdentity\objectTypesIdentityWithConstructSignatures2.js
new compiler generates invalid code:
var b = { new: function new(x) {
return '';
} };
module m1 {
export class C2 implements m3.i3 {
public get p1() {
return null;
}
public f55() {
return "Hello world";
}
}
module m3 {
export interface i3 {
f55(): string;
}
}
class C1 { }
}
Expected: Exported class 'C2' implements private interface 'm3.i3'.
Actual: no error
TypeScript should support emitting minified JavaScript.
There are several different things we could support:
Support ES6-style template strings
http://tc39wiki.calculist.org/es6/template-strings/
To be determined: Can we generate code for pre-ES6 targets? What does that look like?
Code:
//@sourceMap: true
try {
// ...
} finally {
// N.B. No 'catch' block
}
Call stack:
TypeError: Cannot read property 'filename' of undefined
while (true) {
function f() {
break;
}
}
Expected: Jump target cannot cross function boundary.
Actual: no error
Support detecting "use asm" directives and change type inference and operator rules accordingly
"use asm";
var x = 0; // x: int
var y = 0.0: // y: float
var z = (x + y) | 0; // z: int
z = 0.4; // Error, cannot convert float to int
We would need a complete set of type rules for this.
Some properties in JavaScript are actually read-only, i.e. writes to them either fail silently or cause an exception. These should be modelable in TypeScript.
Previous attempts to design this have run into problems. A brief exploration:
interface Point {
x: number;
y: number;
}
interface ImmutablePoint {
readonly x: number;
readonly y: number;
}
var pt: ImmutablePoint = { x: 4, y: 5 }; // OK, can convert mutable to non-mutable
pt.x = 5; // Error, 'pt.x' is not a valid target of assignment
var pt2: Point = pt; // Error, cannot convert readonly 'x' to mutable 'x'
// Possibly bad behavior
var pt3: Point = { x: 1, y: 1 };
var pt4: ImmutablePoint = pt3; // OK
pt3.x = 5; // pt4.x is also changed?
// Really bad behavior
/** This function was written in TypeScript 1.0 **/
function magnitudeSquared(v: { x: number; y: number }) {
return v.x * v.x + v.y * v.y;
}
// Now try to use it with ImmutablePoint
console.log(magnitudeSquared(pt)); // Error, cannot use readonly object in non-readonly call
Possible solutions?
protected
modifier acts the same as private
in terms of code generation and assignability, except that it is possible to access a protected
member in any subclass of a class which declared the member. Basically, you can access protected members in the same situations where it would have been an error for you to redeclare a private
member with the same name as a base class's member.
class Base {
protected myMember;
}
class Derived extends Base {
foo() { return this.myMember; } // OK
}
var x = new Derived();
console.log(x.myMember); // Error, cannot access
class Derived2 extends Base {
private myMember; // Error, cannot tighten visibility
public myMember; // Error, cannot widen visibility
}
After the last design meeting, the following open questions remained:
C# and other IL languages prohibit this pattern, but Java allows it:
class Base { protected x: string; }
class Derived extends Base {
foo(n: Base) {
// Not allowed: cannot reference protected member through base class reference
console.log(n.x);
}
}
See these links for reasoning
http://blogs.msdn.com/b/ericlippert/archive/2008/03/28/why-can-t-i-access-a-protected-member-from-a-derived-class-part-two-why-can-i.aspx
http://stackoverflow.com/questions/1904782/whats-the-real-reason-for-preventing-protected-member-access
protected
members subject to the "same-declaration" rule as private
members for assignability/subtyping?private
members are considered equivalent for the purposes of assignability and subtyping if they are from the "same declaration". This isn't quite the rule you would want for protected members. Consider some classes:
class Widget {
protected inspector: WidgetInspector;
}
class SquareWidget extends Widget {
// Use a more-specific 'inspector'
protected inspector: SquareWidgetInspector;
}
class CircleWidget extends Widget {
// Initialize here
protected inspector: WidgetInspector = new WidgetInspector();
}
var w: Widget;
var c: CircleWidget;
w = c; // Allowed, or not?
If we took the verbatim "same declaration" rule from private
, this assignment would be disallowed because w.inspector
and c.inspector
come from different declarations. It's not reasonable to have this assignment be disallowed.
However, if we do not use the "same declaration" rule, then a SquareWidget
would be assignable to a CirceWidget
even if they both removed their extends
clauses. This is not surprising if you're used to thinking about things structurally, but since many people seem to like the higher specificity of private
in terms of preventing assignability between structurally-equivalent types, this behavior might not be desirable.
A proposed rule was that we could have a notion of a "parent" declaration when a derived class's property overrides a base class property. This seems tractable for classes, but interfaces can extend
multiple classes, and we would need to define what exactly that means. A degenerate example:
interface WatWidget1 extends Widget, CircleWidget { }
interface WatWidget2 extends Widget, SquareWidget { }
var ww1: WatWidget1;
var ww2: WatWidget2;
ww1 = new Widget(); // Allowed or not?
ww1 = new CircleWidget(); // Allowed or not?
ww2 = new Widget(); // Allowed or not?
ww2 = new CircleWidget(); // Allowed or not?
ww1 = ww2;
ww2 = ww1;
class Point1 { x: number }
var p1: Point1 = { x: 3 }; // Allowed
class Point2 { private x: number }
var p2: Point2 = { x: 3 }; // Disallowed
class Point3 { protected x: number }
var p: Point3 = { x: 3 }; // Allowed or not?
This is sort of a yes-or-no thing tangentially related to the previous question.
Many values or parameters in JavaScript can be of more than one type. For example, a function might take an object where one of the properties can be either a string or a number, but not a function.
Comments from Ron Buckton in https://typescript.codeplex.com/workitem/1364
I'd like to see type annotations provide some support for a type union. For example:
class Promise<T> {
// ...
static any<TResult>(...values: union { Promise<T>; T; }[]): Promise<T>;
static every<TResult>(...values: union { Promise<T>; T; }[]): Promise<T[]>;
static some<TResult>(...values: union { Promise<T>; T; }[]): Promise<T>;
then(resolve?: (value: T) => union { Promise<T>; T; }, reject?: (value: any) => union { Promise<T>; T; }): Promise<T>;
// ...
}
class Loader<T> {
// ...
normalize(name: string, referer?: Referer): union { string; { normalized: string; metadata?: any }; };
resolve(normalized: string, options?: { referer: Referer; metadata: any; }): union { string; { address: string; extra?: string[]; }; };
// ...
}
When static type checking is performed, it is possible to have some type issues when explicitly providing generic type arguments and having the wrong type chosen, but this exists today without supporting type unions.
The other open issue is what to do with a local that is a type union: should it act as an any
, a type that contains all of the members of both (or all) types in the union, or a type that only contains the members that are the same in both (or all) types in the union.
An implicit or explicit type cast from a type union to one of the union types would pass without the need to perform an intermediate cast to , and an explicit type cast to a more specific type for any of the union types would likewise succeed without an intermediate cast.
Assignment to a local or field that is a type union would succeed as if it were either of the types (e.g. implicit or explicit type cast from a more specific type to a less specific type specified in the type union).
There is also a question on how to properly handle the intellisense for a symbol that uses a type union. It could either be represented as a number of overloads (similar to what would have to be typed today), or preserve the type union definition.
Providing a typedef-like syntax for unions would also be useful to define a reusable definition:
union Ref<T> {
Promise<T>;
T;
}
This is roughly analogous to an interface that defines multiple call signatures:
// as an interface with call signatures...
interface ResolveCallback<T> {
(value: Promise<T>): void;
(value: T): void;
(): void;
}
// ...and as a union with function types
union ResolveCallback<T> {
(value: Promise<T>) => void;
(value: T) => void;
() => void;
}
Adding type unions would require changes to the static type information to be supported. The primary goal of adding type unions is to help the compiler determine the best matching type for a call expression or return type expression. The following sections discuss various ways of handling static analysis of type unions.
When assigning to an identifier that is annotated with a type union, passing a value as an argument to a function for a parameter that is a type union, returning a value from a function with a type union in its return type annotation, or type-casting a value to a type union, the type of the value being assigned or returned must be compatible (as either an exact match or a superset of type information) with one of the types defined in the type union.
For example:
// assign to variable
var value: union { Promise<number>; number; };
value = 1; // legal
value = Promise.resolve<number>(1); // legal
value = new Date(); // static error
// type-cast to union
declare var n: number;
declare var p: Promise<number>;
declare var a: any;
declare var d: Date;
<union { Promise<number>; number; }>n; // legal
<union { Promise<number>; number; }>p; // legal
<union { Promise<number>; number; }>a; // legal
<union { Promise<number>; number; }>d; // legal
// union in return value
function func(type: string): union { Promise<number>; number; } {
switch (type) {
case "number":
return 1; // legal
case "promise":
return Promise.resolve<number>(1); // legal
case "date":
return new Date(); // static error
}
}
// union in invocation expression
declare function func(promiseOrValue: union { Promise<number>; number; }): void;
declare var n: number;
declare var p: Promise<number>;
declare var a: any;
declare var d: Date;
func(n); // legal
func(p); // legal
func(a); // legal
func(d); // static error
When assigning to another value from a type union or type-casting from a type union, the type of the value must be compatible (as either an exact match or a subset of type information) with one of the types in the union.
For example:
// assignment
declare var value: union { Promise<number>; number; };
var n: number;
var p: Promise<number>;
var a: any;
var d: Date;
n = value; // legal
p = value; // legal
a = value; // legal
d = value; // static error
// type-cast
<Promise<number>>value; // legal
<number>value; // legal
<any>value; // legal
<Date>value; // static error
Input:
module Y { function f(Y) { return g; } export var g;}
Emit:
var Y;
(function (Y) {
function f(Y) {
return Y.g; <-- wrong
}
Y.g;})(Y || (Y = {}));
Expected emit:
var Y;
(function (_Y) {
function f(Y) {
return _Y.g;
}
_Y.g;})(Y || (Y = {}));
module m1 {
export class C2 implements m3.i3 {
public get p1() {
return new C1();
}
public f55() {
return "Hello world";
}
}
module m3 {
export interface i3 {
f55(): string;
}
}
class C1 { }
}
Expected:
Exported class 'C2' implements private interface 'm3.i3'. Return type of public property getter from exported class has or is using private type 'C1'.
Actual: no error
Consider the following source file:
/*
While it may be difficult to spot, this is an unclosed comment. We should report an error on this.
var x = 1;
break;
continue;
Expected:
'break' statement can only be used within an enclosing iteration or switch statement.
'continue' statement can only be used within an enclosing iteration statement.
Actual: no error
Error must be syntactic.
Perf tests has an old format of the /// reference:
///<reference path='..\typings\winjs.d.ts' static='true' />
Expected:
extract the file from the path, and ignore the static attribute
Actual: error
See title.
while (true) { break target; }
Expected: Jump target not found.
Actual: no error
interface Foo {
x: number;
}
export class Bar {
f(x: Foo) { }
}
Expected: Parameter 'x' of public method from exported class has or is using private type 'Foo'.
Actual: no error
A common error in TypeScript is to lose the this
context, especially in class situations:
class MyClass {
x = 4;
printX() { console.log(this.x); }
}
var m = new MyClass();
window.setInterval(m.printX, 1000); // Prints 'undefined', not '4'
The compiler should detect when this happens and issue an error:
var m = new MyClass();
// Error, `this` context might be lost
window.setInterval(m.printX, 1000);
We need a proposal here that determines why this would be an error, in a way that is not burdensome. For example, we do want it to be valid to call e.g. function#bind
on m.printX
, and it should probably valid to write something like if(m.printX) { m.printX() }
.
This gets even trickier when we look at the members of window
-- some of them can be invoked with any this
, but others cannot. It should be possible to describe these differences.
Code (should have an error):
function fn(): string {
}
interface Promise<T> {
then<U>(success?: (value: T) => U, error?: (error: any) => U, progress?: (progress: any) => void): Promise<U>;
done<U>(success?: (value: T) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;
}
interface IPromise<T> {
then<U>(success?: (value: T) => IPromise<U>, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: T) => IPromise<U>, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: T) => U, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: T) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
done? <U>(success?: (value: T) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;
}
declare function testFunction11(x: number): IPromise<number>;
declare function testFunction11(x: string): IPromise<string>;
declare function testFunction11P(x: number): Promise<number>;
declare function testFunction11P(x: string): Promise<string>;
var s11: Promise<number>;
var s11a = s11.then(testFunction11, testFunction11, testFunction11); // ok
var s11b = s11.then(testFunction11P, testFunction11P, testFunction11P); // ok
var s11c = s11.then(testFunction11P, testFunction11, testFunction11); // ok
Used to all succeed, but now they all fail. This is because when we collect candidates for U from testFunction11 and testFunction11P, we only use the last overload instead of all the overloads. This is an algorithmic change in the new compiler.
They used to all succeed, but they were Promise<{}>, which is not super meaningful anyway.
r11a has similar behavior in promisePermutations3.ts
Repro consists of:
/// <reference path="typings\c.d.ts" />
declare class Promise<T> {
x: T;
}
/// <reference path="b.d.ts" />
/// <reference path="..\a.ts" />
Invoke: tc Typings\c.d.ts
Result:
Symbol.declarations, function (d) { return d.parent === currentNode.parent; }
TypeError: Cannot read property 'parent' of undefined
See title
In tests/cases/compiler/privacyTopLevelInternalReferenceImportWithExport.ts:
Everything declaration of the form:
im_public__private
or
im_public__public
is not emitted.
In tests/cases/compiler/privacyTopLevelInternalReferenceImportWithoutExport.ts:
Everything declaration of the form:
im_private__private
or
im_private__public
is not emitted.
For both cases, used to emit:
var im_private_c_public = m_public . c_public ;
and the like
module M {
module N { }
export import X = N;
}
Expected:
!!! Exported import declaration 'X' is assigned container that is or is using inaccessible module 'N'.
Actual: no error
Similar errors in
tests/cases/compiler/privacyLocalInternalReferenceImportWithExport.ts
module M{
export class C { }
export module C {
export var C = M.C
}}
Expected:
var M;
(function (M) {
var C = (function () {
function C() { }
return C;
})();
M.C = C;
(function (_C) {
_C.C = M.C;
})(M.C || (M.C = {}));
var C = M.C;
})(M || (M = {}));
Actual:
var M;
(function (M) {
var C = (function () {
function C() { }
return C;
})();
M.C = C;
(function (C) {
C.C = M.C;
})(M.C || (M.C = {}));
var C = M.C;
})(M || (M = {}));
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.