DEV Community

Masui Masanori
Masui Masanori

Posted on

[TypeScript] Try ...

Intro

When I write TypeScript code I sometime use "..."(Three dots).
But because I haven't known so much, so I decided to try using it in some cases.

Environments

  • TypeScript ver.4.2.4

"..." in JavaScript

I can use "..." for two ways in JavaScript.
They are "Spread syntax" and "Rest parameters".

TypeScript "..." behavior also comes from them.

Spread syntax

I can copy parameters or array items to other object or array.

type Print = {
    message: string,
    width: number,
    height: number,
    x: number,
    y: number,
};
type Size = {
    width: number,
    height: number,
};
function start() {
    let sampleSize = {
        width: 1920,
        height: 1080
    };
    const samplePrint = {
        message: 'Hello',
        x: 10,
        y: 50,
        ...sampleSize
    };
    print(samplePrint);
    const array1 = ['Hello', 'World', '!!!'];
    const array2 = [...array1];
    printArray(array2);
}
function print(target: Print) {
    console.log('Print');
    console.log(target);
}
function printArray(targets: readonly string[]) {
    console.log('Print Array');
    console.log(targets);
}
Enter fullscreen mode Exit fullscreen mode

Result

Print
{ message: 'Hello', x: 10, y: 50, width: 1920, height: 1080 }
Print Array
[ 'Hello', 'World', '!!!' ]
Enter fullscreen mode Exit fullscreen mode

It copies values and object references(not properties).

...
type Position = {
    x: number,
    y: number,
};
type Rect = {
    size: Size,
    position: Position
};
function start() {
    let sampleSize = {
        width: 1920,
        height: 1080
    };
    const samplePrint = {
        message: 'Hello',
        x: 10,
        y: 50,
        ...sampleSize
    };
    // samplePrint.width isn't changed
    sampleSize.width = 300;
    print(samplePrint);
...
    const samplePosition: Position = {
        x: 30,
        y: 5
    };
    const sampleRect = {
        size: sampleSize,
        position: samplePosition
    };
    const wrapSample = {
        ...sampleRect
    };
    // wrapSample.size.width is changed to 400
    sampleSize.width = 400;
    printRect(wrapSample);
}
...
Enter fullscreen mode Exit fullscreen mode

Result

Print
{ message: 'Hello', x: 10, y: 50, width: 1920, height: 1080 }
...
printRect
{ size: { width: 400, height: 1080 }, position: { x: 30, y: 5 } }
Enter fullscreen mode Exit fullscreen mode

It only copies properties.

...
class BaseClass {
    public size: Size = {
        width: 10,
        height: 10
    };
    public print() {
        console.log('Hello');
    }
}
class ExtendClass extends BaseClass {
    public position: Position = {
        x: 0,
        y: 50
    };
    public print2() {
        console.log('World');
    }
}
function start() {
...
    const sampleClass = new ExtendClass();
    // this only has "size" and "position".
    // methods aren't copied
    const copiedClass = {
        ...sampleClass
    };
}
...
Enter fullscreen mode Exit fullscreen mode

Rest parameters

I can set 0 ~ n arguments for functions or methods.

...
function start() {
...
    printArgs();
    printArgs('Hello');
    printArgs('Hello', 'World');
}
...
function printArgs(...args: string[])
{
    console.log('printArgs');
    console.log(args);
}
// compile error. rest parameters must be the last argument
function printArgsFailed(...args1: number[], ...args2: string[])
{
    console.log('printArgsFailed');
}
...
Enter fullscreen mode Exit fullscreen mode

Result

...
printArgs
[]
printArgs
[ 'Hello' ]
printArgs
[ 'Hello', 'World' ]
Enter fullscreen mode Exit fullscreen mode

I also can separate the parameters.

...
function start() {
...
    printSeparatedArgs();
    printSeparatedArgs('Hello');
    printSeparatedArgs('Hello', 'World');
    printSeparatedArgs('Hello', 'World', '!!!');
}
...
function printSeparatedArgs(...[a, b]: string[])
{
    console.log('printSeparatedArgs');
    console.log(a);
    console.log(b);
}
...
Enter fullscreen mode Exit fullscreen mode

Result

...
printSeparatedArgs
undefined
undefined
printSeparatedArgs
Hello
undefined
printSeparatedArgs
Hello
World
printSeparatedArgs
Hello
World
Enter fullscreen mode Exit fullscreen mode

I also can separate array by rest parameters.

...
function start() {
...
    printTail();
    printTail('Hello', 'World');
    printTail('Hello', 'World', '!!!');
}
...
function printTail<T extends any[]>(...args: T) {
    const [_, ...result] = args;
    console.log('printTail');
    console.log(result);
}
...
Enter fullscreen mode Exit fullscreen mode

Result

...
printTail
[]
printTail
[ 'World' ]
printTail
[ 'World', '!!!' ]
Enter fullscreen mode Exit fullscreen mode

Variadic Tuple Types

From TypeScript 4.0, I can use "..." two or more times for defining Tuple type.

...
function start() {
...
    const array1 = ['Hello', 'World', '!!!'];
...    
    const nums = [1, 12, 30];
    console.log('Tuple');
    console.log(getTuple(nums, array1));
}
...
function getTuple<T extends number[], U extends string[]>(t: T, u: U): [...T , ...U] {
    return [...t, ...u];
}
...
Enter fullscreen mode Exit fullscreen mode

Result

...
Tuple
[ 1, 12, 30, 'Hello', 'World', '!!!' ]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)