简体   繁体   中英

How to write an interface represents a tuple type in TypeScript?

Glad to see the release of TypeScript 1.3, but how to write an interface represents a tuple type?

Eg

var data: [string, number, number];

How to write an interface IData so that I would be able to do the same thing by writing

var data: IData;

I know this is an old question, but I think you can accomplish what you want with the following:

type IData = [string, number, number];

then

var data: IData;

You can see this in this TypeScript Playground example

Note that with some of the new features coming, such as union types, you can get roughly what you want. The latest draft of the spec contains an example along these lines (see https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.3.3 )

The below code shows an example of how this might look:

interface KeyValuePair extends Array<string | number> { 0: string; 1: number; }

var x: KeyValuePair = ["test", 42]; // OK
var y: KeyValuePair = [42, "test"]; // Error

If you grab the latest code from the master branch and compile the above, you'll see where it detects the assignment to 'x' as valid, and the assignment to 'y' as an error:

S:\src\TypeScript\bin>node tsc c:\temp\tuple.ts
c:/temp/tuple.ts(4,5): error TS2323: Type '[number, string]' is not assignable to type 'KeyValuePair'.
  Types of property '0' are incompatible.
    Type 'number' is not assignable to type 'string'.

Much more boilerplateness approach than Joe Skeen's, but allows compile time type checks. And boilerplate util code write just once.. ;)

function usage(t: CortegeOf2<boolean, string>) {
    get1(t).toLowerCase(); //ok

    // var trash1 = t[2]; //runtime error
    // var e0 = get2(t); //compile-time error we cannot get 2nd element cuz t has only 0th and 1st

    // var trash2: string = t[1]; //sadly that syntax allows to pass value somewhere, where expected another type
    // trash2.toUpperCase(); //runtime error

    // var e2: string = get1(t); //but that usage will not allow that pass
}


export interface CortegeOf1<T0> {
    0: T0;
}

export interface CortegeOf2<T0, T1> extends CortegeOf1<T0> {
    1: T1;
}

export interface CortegeOf3<T0, T1, T2> extends CortegeOf2<T0, T1> {
    2: T2;
}

export function get0<T>(cortege: CortegeOf1<T>): T {
    return cortege[0];
}

export function get1<T>(cortege: CortegeOf2<any, T>): T {
    return cortege[1];
}

export function get2<T>(cortege: CortegeOf3<any, any, T>): T {
    return cortege[2];
}

Can be used with arrays:

export function joinTwo<A, B>(a: Promise<A>, b: Promise<B>): Promise<CortegeOf2< A, B >> {
    return Promise.all([a, b]);
}

function joinThree<A, B, C>(a: Promise<A>, b: Promise<B>, c: Promise<C>): Promise<CortegeOf3< A, B, C >> {
    return Promise.all([a, b, c]);
}

You can not create an interface from a Tuple, like you can not make one from a string either.

You can use a Tuple in an interface like:

interface IDATA {
   value: [number, string];
}

Little Late, but I think this approach is quite nice and simple and could help others:

type Type<T> = T;

interface IData extends Type<[number, number, number]>
{

}

var data: IData = ["Some Data", 42, 42];

This works also with Objects, if someone needs it:

type Type<T> = T;

interface IData extends Type<{ data: string }>
{

}

var data: IData = { data: "Some Data" };

You can also do this:

interface IData
{
    0: string;
    1: number;
    2: number;
}

var data: IData = ["Some Data", 42, 42];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM