microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.4k stars 12.4k forks source link

Incompleteness of the variable name and type name is the same definition #1264

Closed falsandtru closed 9 years ago

falsandtru commented 9 years ago

Developers can not declare the type of several variables.

Several lib.d.ts interfaces is defined the type of instance. The type of the variable can not be defined in a different variable. That is, the variable type is not defined.

TypeScript does not provide the type definition of several variable.

I understand that it is difficult to realize the required only the name of the types in the specification. TypeScript adds another definition, or give up static variable type definitions, it is this selection.

How corresponding to this problem? I want to know the development policy.

DanielRosenwasser commented 9 years ago

Sorry, I'm not sure if I understand what you're asking. Could you give a concrete example to demonstrate the limitation you're running into?

falsandtru commented 9 years ago

Sorry, I will explain the abstract examples and specific examples.

First, there is a case-defined name of the W3C's interface is the same as the variable name. W3C's interface can be defined both members of variables and instance.

//W3C spec if
//interface Example {
//    attribute any a;
//    static any b;
//};
window.Example.a // not exists
window.Example.b // exists

Then, if the TypeScript implements this interface, TypeScript have implemented only instance rather than variable interface. Because TypeScript can not define a static member. TypeScript must discard the static type definition of the interface.

//Conversion from W3C to TypeScript
interface Example {
    a: any; // support
    static b: any; // not support
};
//TypeScript implements
interface Example {
    a: any;
};
declare var Example: {
    b: any;
}

It is not declarable the type of the variable. But TypeScript should have a type that W3C has defined.

var E: Example = <any>{}
E.b // signature error because b is not type defined, but W3C is defined.

TypeScript can not solve the problem of this case if TypeScript can not type definition of static members to the interface.

define variable(not declarable) variable type(declarable) instance type(declarable)
W3C - O O
TypeScript O X O

There is actually an example of this problem is occurring.

http://www.w3.org/TR/IndexedDB/#range-concept

interface IDBKeyRange { readonly attribute any lower; readonly attribute any upper; readonly attribute boolean lowerOpen; readonly attribute boolean upperOpen; static IDBKeyRange only (any value); static IDBKeyRange lowerBound (any lower, optional boolean open); static IDBKeyRange upperBound (any upper, optional boolean open); static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen, optional boolean upperOpen); };

// IDBKeyRange definition has variable only member.
interface IDBKeyRange {
    upper: any; // interface only
    upperOpen: boolean; // interface only
    lower: any; // interface only
    lowerOpen: boolean; // interface only
}
declare var IDBKeyRange: {
    prototype: IDBKeyRange;
    new(): IDBKeyRange;
    bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange; // VARIABLE ONLY!!
    only(value: any): IDBKeyRange; // VARIABLE ONLY!!
    lowerBound(bound: any, open?: boolean): IDBKeyRange; // VARIABLE ONLY!!
    upperBound(bound: any, open?: boolean): IDBKeyRange; // VARIABLE ONLY!!
}
var holder: IDBKeyRange = IDBKeyRange // signature error
IDBKeyRange.only // ok
holder.only // error

TypeScript is to possible declare all of the W3C defined types? Or admit the existence of impossible declaration type?

TypeScript will allow the type information that can not be declared, it is not a full compliance with W3C. If it's TypeScript policy, I give up. But I want the declarable type definition of all of W3C spec.

danquirk commented 9 years ago

The choices here are:

a) Use an interface. As you said, you cannot define statics in an interface since an interface only defines the instance side of a type. But you can use interfaces to define types that are not constructable or types that can be extended (through merged interface definitions). You could write an interface that describes the static side of a type and merge it with a declaration of another kind (ex a function or variable), see JQuery.d.ts for an example of this with $.

b) Use a class. Now you can define instances and statics but you must have a constructor and other class definitions cannot be merged with this one (see #819).

falsandtru commented 9 years ago

I also know how to resolve both. However, it is not the purpose of this issue.

TypeScript is to possible declare all of the W3C defined types? Or admit the existence of impossible declaration type?

TypeScript will allow the type information that can not be declared, it is not a full compliance with W3C. If it's TypeScript policy, I give up. But I want the declarable type definition of all of W3C spec.

define variable(not declarable) variable type(declarable) instance type(declarable)
W3C - O O
TypeScript O X O
danquirk commented 9 years ago

In your concrete example, remove the type annotation and things work:

var holder = IDBKeyRange // ok
IDBKeyRange.only // ok
holder.only // ok

Alternatively, your type annotation should use typeof

var holder: typeof IDBKeyRange = IDBKeyRange // ok
IDBKeyRange.only // ok
holder.only // ok

The pattern IDBKeyRange uses in lib.d.ts is how you model the static side of the W3C spec like this. Interfaces only describe the instance shape so you need to use a combination of declarations to model these sorts of types. The problem with this approach is you cannot extend the static side further. Allowing class declarations to be merged/extended would be one way to enable this scenario in the future.

falsandtru commented 9 years ago

I wanted the feature! I use the typeof. Thank you.