Typescript基礎まとめ2

typescriptを理解するために書き殴っていきます。

##関数で使われる特別な型
####void型
>void 【形】中身がない、空っぽの

voidは関数の返り値として扱われ、「何も返さない」ことを表す型。
javascriptでは何も返さない関数（return文がない　or　返り値のないreturn文で返る）は、undifindを返す。
なので、void型というのは、undefinedのみを値に取る型となる。
なので、void型の変数には、undefinedを入れることができる。
ただし、void型の値をundefined型の変数に入れることはできない。

```
  const a: void = undefined;
  //error　: Type 'void' is not assignable to type 'undefined'.
  //エラー : 型'void'は型'undefined'に割り当てることはできません。
  const b: undefined = a;
```
これは、void型の関数というのは、あくまでも何も返さない関数なのだから、その値を利用することはできないという意図があると考えられる。

void型の主な使い所は、関数の返り値としてがある。何も返さない関数の返り値の型として、void型を使う。
void型はある意味特殊な型であり、返り値がvoidである関数は、値を返さなくてもよくなる。
対してそれ以外の型の場合（any型を除く）は、必ず返り値を返さなければならない。

```
  function foo(): void {
    console.log('Hey');
 } 

//エラー: 宣言された型が'void'でも'any'でもない関数は、値を返さなければなりません。
  function bar(): undefined {
    console.log('Sakai!');
 }
```

####never型

決して戻ることのない関数の戻り値。
詳しくは後述します。

##関数の部分型関係

```
  interface Obj1 {
    foo: string;
    bar: number;
 }

  interface Obj2 {
    foo: string;
  }

  const a: (obj: Obj2)=>void = ()=>{};
  const b: (obj: Obj1)=>void = ()=>{};
```

上記の例から見えるように、(obj: Obj2)=>void型の値を、（obj: Obj）=>void型の値として扱うことができる。
なぜなら、Obj1はObj2の部分型なので、Obj2を受け取って処理できる関数ならば、Obj1を受け取っても同然処理できるということだからだ。
キーにfooを持つstring型の引数をObj1、Obj2の両者は持っている。
aは引数に、キーにfooを持つstring型の値のを持つ型が定義されている（Obj2）が、
bは引数に、キーにfooを持つstring型の値+キーにbarを持つnumber型の値を持つ型が宣言されている。

javascriptでシンプルに表すと以下のように表すことができる。

```
  const a = ("こんにちは") => {
  }

  const b = ("こんにちは"、3) => {
  }
```

つまり、
「関数aで処理できる内容ならば、関数bでも処理することができるよね」
「でも、関数bで処理する内容は、関数aでは処理できないよね」
ということだ。

##可変長引数とレストパラメーター（残余引数）
javascriptには、可変長引数というものがある。
これは、個数が変動する引数のことである。
それを表す方法として、レストパラメータ（残余引数）というものがある。
それは、（foo, ...bar）=> barのように、最後の引数を...barのようにすると、それ以降の引数が全部入った配列がbarに渡されるというもの。

```
const func = (foo, ...bar)=> bar;

console.log(func(1,2,3)); //[2,3]
```

tsでも可変超引数の関数を宣言することができる。

```
  const func = (foo: string, ...bar: number[]) => bar;

  func('foo');
  func('bar', 1, 2, 3);
  //エラー
  func('baz', 'hey', 2, 3);
```

上の例では、...barにnumber[]型がついているため、二番目以降の引数は全て数値でなければならない。

##any型

なんでもありな型。
どんな型とも相互交換可能であり、実質TypeScriptのシステムを無視することに相当する。
これを使うと型システムを欺くことが可能になってしまい、TypeScriptを使っている意味が薄れてしまう。
TypeScriptはこの型を避けるゲーム。

```
  const a: any = 3;
  const b: string = a;
```

##クラスの型

javascriptにはクラスを定義する構文がある
あq

```
  class Foo {
    method(): void {
      console.log('Hello, world!');
    }
  }

  const obj: Foo = new Foo();
```

##ジェネリクス

型がある言語にはジェネリクスというものがよく存在する。
>ジェネリクス：　ジェネリクスとは、プログラミング言語の機能・仕様の一つで、同じプログラムコードで様々なデータ型のデータを処理できるようにするもの。 C++言語などではほぼ同様の機能を「テンプレート」と呼ぶ。

多相型に関連するもの。
>多層的：　層が多いこと。 複数の要素が積み重なっている構造を表現する言葉。

型変数を用いることで、動的な型宣言を行うことができる。

型名をFoo\<S, T>のようにする、すなわち名前の後に、<>で囲った名前の列を与えることで、型の定義の中でそれらの名前を型変数として使うことができる。

```
  interface Foo<S, T> {
    foo: S;
    bar: T;
  }

  const obj: Foo<number, string> = {
    foo: 3,
    bar: 'hi',
  };
```

この例ではFooは2つの型変数S,Tを持つ。Fooを使う側ではFoo<number, string>のように、
SとTに当てはまる型を指定する。

他に、クラス定義や関数定義でも型変数を導入できる。

```
  class Foo<T> {
    constructor(obj: T) {
    }
  }

  const obj1 = new Foo<string>('foo');

  function func<T>(obj: T): vold {
  }

  func<number>(3);
```

##タプル型

>タプルとは、順序付けられた複数の要素で構成される組。 もとは数学の概念だが、プログラミング言語などの中には同様の構造を持つタプルという名称のデータ型が用意されている

TypeScriptはタプル型という方も用意している。
ただし、javascriptにはタプルという概念はない。
そこで、typescriptでは、配列をタプルの代わりとして用いることにしている。
これは、関数から複数の値を返したい場合に配列に入れてまとめて返すみたいなユースケースを想定していると思われる。

タプル型は[string, number]のように書く。

```
  const foo: [string, number] = ['foo', 5];

  const str: string = foo[0];

  function makePair(x: string, y: number): [string, number] {
    return [x, y];
  }
```

#####配列型とタプル型の違い
配列型→　number[]　:numberの配列ですよ
タプル型→ [string, number] :1番目にstring、二番目にnumberを持つ配列ですよ