3.9 Specifying Members

The members of an object type literal (section 3.8.3) are specified as a combination of property, call, construct, index, and method signatures.

3.9.1 Property Signatures

A property signature declares the name and type of a property member.

  PropertySignature:   PropertyName?optTypeAnnotationopt

  TypeAnnotation:   :Type

The PropertyName (2.2.2) of a property signature must be unique within its containing type, and must denote a well-known symbol if it is a computed property name (2.2.3). If the property name is followed by a question mark, the property is optional. Otherwise, the property is required.

If a property signature omits a TypeAnnotation, the Any type is assumed.

3.9.2 Call Signatures

A call signature defines the type parameters, parameter list, and return type associated with applying a call operation (section 4.15) to an instance of the containing type. A type may overload call operations by defining multiple different call signatures.

  CallSignature:   TypeParametersopt(ParameterListopt)TypeAnnotationopt

A call signature that includes TypeParameters (section 3.6.1) is called a generic call signature. Conversely, a call signature with no TypeParameters is called a non-generic call signature.

As well as being members of object type literals, call signatures occur in method signatures (section 3.9.5), function expressions (section 4.10), and function declarations (section 6.1).

An object type containing call signatures is said to be a function type.

3.9.2.1 Type Parameters

Type parameters (section 3.6.1) in call signatures provide a mechanism for expressing the relationships of parameter and return types in call operations. For example, a signature might introduce a type parameter and use it as both a parameter type and a return type, in effect describing a function that returns a value of the same type as its argument.

Type parameters may be referenced in parameter types and return type annotations, but not in type parameter constraints, of the call signature in which they are introduced.

Type arguments (section 3.6.2) for call signature type parameters may be explicitly specified in a call operation or may, when possible, be inferred (section 4.15.2) from the types of the regular arguments in the call. An instantiation of a generic call signature for a particular set of type arguments is the call signature formed by replacing each type parameter with its corresponding type argument.

Some examples of call signatures with type parameters follow below.

A function taking an argument of any type, returning a value of that same type:

  1. <T>(x: T): T

A function taking two values of the same type, returning an array of that type:

  1. <T>(x: T, y: T): T[]

A function taking two arguments of different types, returning an object with properties ‘x’ and ‘y’ of those types:

  1. <T, U>(x: T, y: U): { x: T; y: U; }

A function taking an array of one type and a function argument, returning an array of another type, where the function argument takes a value of the first array element type and returns a value of the second array element type:

  1. <T, U>(a: T[], f: (x: T) => U): U[]
3.9.2.2 Parameter List

A signature’s parameter list consists of zero or more required parameters, followed by zero or more optional parameters, finally followed by an optional rest parameter.

  ParameterList:   RequiredParameterList   OptionalParameterList   RestParameter   RequiredParameterList,OptionalParameterList   RequiredParameterList,RestParameter   OptionalParameterList,RestParameter   RequiredParameterList,OptionalParameterList,RestParameter

  RequiredParameterList:   RequiredParameter   RequiredParameterList,RequiredParameter

  RequiredParameter:   AccessibilityModifieroptBindingIdentifierOrPatternTypeAnnotationopt   BindingIdentifier:StringLiteral

  AccessibilityModifier:   public   private   protected

  BindingIdentifierOrPattern:   BindingIdentifier   BindingPattern

  OptionalParameterList:   OptionalParameter   OptionalParameterList,OptionalParameter

  OptionalParameter:   AccessibilityModifieroptBindingIdentifierOrPattern?TypeAnnotationopt   AccessibilityModifieroptBindingIdentifierOrPatternTypeAnnotationoptInitializer   BindingIdentifier?:StringLiteral

  RestParameter:   ...BindingIdentifierTypeAnnotationopt

A parameter declaration may specify either an identifier or a binding pattern (5.2.2). The identifiers specified in parameter declarations and binding patterns in a parameter list must be unique within that parameter list.

The type of a parameter in a signature is determined as follows:

  • If the declaration includes a type annotation, the parameter is of that type.
  • Otherwise, if the declaration includes an initializer expression (which is permitted only when the parameter list occurs in conjunction with a function body), the parameter type is the widened form (section 3.12) of the type of the initializer expression.
  • Otherwise, if the declaration specifies a binding pattern, the parameter type is the implied type of that binding pattern (section 5.2.3).
  • Otherwise, if the parameter is a rest parameter, the parameter type is any[].
  • Otherwise, the parameter type is any.

A parameter is permitted to include a public, private, or protected modifier only if it occurs in the parameter list of a ConstructorImplementation (section 8.3.1) and only if it doesn’t specify a BindingPattern.

A type annotation for a rest parameter must denote an array type.

When a parameter type annotation specifies a string literal type, the containing signature is a specialized signature (section 3.9.2.4). Specialized signatures are not permitted in conjunction with a function body, i.e. the FunctionExpression, FunctionImplementation, MemberFunctionImplementation, and ConstructorImplementation grammar productions do not permit parameters with string literal types.

A parameter can be marked optional by following its name or binding pattern with a question mark (?) or by including an initializer. Initializers (including binding property or element initializers) are permitted only when the parameter list occurs in conjunction with a function body, i.e. only in a FunctionExpression, FunctionImplementation, MemberFunctionImplementation, or ConstructorImplementation grammar production.

TODO: Update to reflect binding parameter cannot be optional in implementation signature.

TODO: Update to reflect required parameters support initializers.

3.9.2.3 Return Type

If present, a call signature’s return type annotation specifies the type of the value computed and returned by a call operation. A void return type annotation is used to indicate that a function has no return value.

When a call signature with no return type annotation occurs in a context without a function body, the return type is assumed to be the Any type.

When a call signature with no return type annotation occurs in a context that has a function body (specifically, a function implementation, a member function implementation, or a member accessor declaration), the return type is inferred from the function body as described in section 6.3.

3.9.2.4 Specialized Signatures

When a parameter type annotation specifies a string literal type (section 3.2.9), the containing signature is considered a specialized signature. Specialized signatures are used to express patterns where specific string values for some parameters cause the types of other parameters or the function result to become further specialized. For example, the declaration

  1. interface Document {
  2. createElement(tagName: "div"): HTMLDivElement;
  3. createElement(tagName: "span"): HTMLSpanElement;
  4. createElement(tagName: "canvas"): HTMLCanvasElement;
  5. createElement(tagName: string): HTMLElement;
  6. }

states that calls to ‘createElement’ with the string literals “div”, “span”, and “canvas” return values of type ‘HTMLDivElement’, ‘HTMLSpanElement’, and ‘HTMLCanvasElement’ respectively, and that calls with all other string expressions return values of type ‘HTMLElement’.

When writing overloaded declarations such as the one above it is important to list the non-specialized signature last. This is because overload resolution (section 4.15.1) processes the candidates in declaration order and picks the first one that matches.

Every specialized call or construct signature in an object type must be assignable to at least one non-specialized call or construct signature in the same object type (where a call signature A is considered assignable to another call signature B if an object type containing only A would be assignable to an object type containing only B). For example, the ‘createElement’ property in the example above is of a type that contains three specialized signatures, all of which are assignable to the non-specialized signature in the type.

3.9.3 Construct Signatures

A construct signature defines the parameter list and return type associated with applying the new operator (section 4.14) to an instance of the containing type. A type may overload new operations by defining multiple construct signatures with different parameter lists.

  ConstructSignature:   newTypeParametersopt(ParameterListopt)TypeAnnotationopt

The type parameters, parameter list, and return type of a construct signature are subject to the same rules as a call signature.

A type containing construct signatures is said to be a constructor type.

3.9.4 Index Signatures

An index signature defines a type constraint for properties in the containing type.

  IndexSignature:   [BindingIdentifier:string]TypeAnnotation   [BindingIdentifier:number]TypeAnnotation

There are two kinds of index signatures:

  • String index signatures, specified using index type string, define type constraints for all properties and numeric index signatures in the containing type. Specifically, in a type with a string index signature of type T, all properties and numeric index signatures must have types that are assignable to T.
  • Numeric index signatures, specified using index type number, define type constraints for all numerically named properties in the containing type. Specifically, in a type with a numeric index signature of type T, all numerically named properties must have types that are assignable to T.

A numerically named property is a property whose name is a valid numeric literal. Specifically, a property with a name N for which ToString(ToNumber(N)) is identical to N, where ToString and ToNumber are the abstract operations defined in ECMAScript specification.

An object type can contain at most one string index signature and one numeric index signature.

Index signatures affect the determination of the type that results from applying a bracket notation property access to an instance of the containing type, as described in section 4.13.

3.9.5 Method Signatures

A method signature is shorthand for declaring a property of a function type.

  MethodSignature:   PropertyName?optCallSignature

If the PropertyName is a computed property name (2.2.3), it must specify a well-known symbol. If the PropertyName is followed by a question mark, the property is optional. Otherwise, the property is required. Only object type literals and interfaces can declare optional properties.

A method signature of the form

  1. f < T1, T2, ... > ( p1, p2, ... ) : R

is equivalent to the property declaration

  1. f : { < T1, T2, ... > ( p1, p2, ... ) : R }

A literal type may overload a method by declaring multiple method signatures with the same name but differing parameter lists. Overloads must either all be required (question mark omitted) or all be optional (question mark included). A set of overloaded method signatures correspond to a declaration of a single property with a type composed from an equivalent set of call signatures. Specifically

  1. f < T1, T2, ... > ( p1, p2, ... ) : R ;
  2. f < U1, U2, ... > ( q1, q2, ... ) : S ;
  3. ...

is equivalent to

  1. f : {
  2. < T1, T2, ... > ( p1, p2, ... ) : R ;
  3. < U1, U2, ... > ( q1, q2, ... ) : S ;
  4. ...
  5. } ;

In the following example of an object type

  1. {
  2. func1(x: number): number; // Method signature
  3. func2: (x: number) => number; // Function type literal
  4. func3: { (x: number): number }; // Object type literal
  5. }

the properties ‘func1’, ‘func2’, and ‘func3’ are all of the same type, namely an object type with a single call signature taking a number and returning a number. Likewise, in the object type

  1. {
  2. func4(x: number): number;
  3. func4(s: string): string;
  4. func5: {
  5. (x: number): number;
  6. (s: string): string;
  7. };
  8. }

the properties ‘func4’ and ‘func5’ are of the same type, namely an object type with two call signatures taking and returning number and string respectively.