Closed13

なんとなくでやってたTypeScript + 少しReactを再学習する

こまきちこまきち

型定義

String, Number, Bool

let name: String = "string";
let number: number = 1;
let bool: boolean = true;

オブジェクト

interfaceを使用する

interface hoge {
  first: string;
  second: string;
  third: string;
}

let hogeObj: hoge = { first: "俺", second: "お前", third: "友達" }

null許容

interface hoge {
  first: string;
  second: string | null;
}

関数

返り値の型を明示的に宣言することが可能

const func1 = (x: number, y: number): number => {
  return x + y;
}
こまきちこまきち

Intersection Types

2つのオブジェクト型のタイプを結合する型のこと

type Profile = {
  age: number;
  city: string;
}

type Login {
  username: string;
  password: string;
}

type User = Profile & Login;

// 使い方
const userA: User {
  age: 30;
  city: "Tokyo";
  username: "hoge";
  password: "password";
}
こまきちこまきち

Union Types

変数が受け取れるデータ型を制限することができる。

let value: boolean | number;
value = true;        // ok
value = "string";  // error

// 配列内の型制限も可能
let arrayUni: (number | string)[];
arrayUni = [0, 1, 2, "hello", 3];        // ok
arrayUni = [0, 1, 2, "hello", true];   //  error

こまきちこまきち

リテラル

変数に入れることができるデータを制限する。

let company: "Facebook" | "Google" | "Amazon";
company = "Amazon";  // ok
company = "Apple"   // error
こまきちこまきち

typeof

宣言済変数の型を取得する

let message: string = "Hello";
let message2: typeof message = "World";

// オブジェクト
let animal = { cat: "this is a cat" };
let newAnimal : typeof animal = { cat: "that is a cat" };
こまきちこまきち

keyof

属性の名前をUnion Typeで取り出し、それ以外の型を受け付けないようにする。

type Keys = {
  primary: string;
  secondary: string;
}

let key: keyof Keys;
key = "primary";  // ok
key = "none"   // error

typeof + keyof

const Sports = {
  soccer: "Soccer";
  baseball: "Baseball";
}

/*
 typeof Sports =  データ型をそのまま継承
 keyof Sports = 属性の名前を取り出し、Union Typeとする
 → 結果としてUnion Typeになる。
*/
let keySports: keyof typeof Sports;
keySports = "Soccer";  // ok
keySports = "soccer";  // error
こまきちこまきち

enum

列挙型。自動で連番をつけてくれる。
列挙型を使うことでバグの発生を防ぐことができ、メンテナンス性も向上する。

enum OS {
  windows,
  Mac,
  Linux,
}

interface PC {
  id: number;
  OSType: OS;
}

const PC1: PC = {
  id: 1,
  OSType: OS.windows,
}

const PC1: PC = {
  id: 2,
  OSType: OS.Mac,
}
こまきちこまきち

型の互換性

抽象度の高い要素に具体的な要素を代入することは可能だが、その逆は不可。

OKな例

const comp1 = "test";  // データ型→ comp1: "test"
let comp2: string = comp1;  // ok

Errorな例

let comp3: string = "test";
let comp4: "test" = comp3;  // error
こまきちこまきち

ジェネリックス

使う時にinterfaceに型定義をすることで、コードの汎用性を高めることができる。

interface Gen<T>{
  item: T;
}

const gen0: Gen<string> = { item: "hello" };  // ok
const gen1: Gen = { item: "hello" };  // error

デフォルトの型を指定する

interface Gen1<T = string>{
  item: T;
}

const gen0: Gen1<string> = { item: "hello" };  // ok
const gen1: Gen1 = { item: "hello" };  // ok

型制限をかける

interface Gen2<T extends string | number> {
  item: T;
}

const gen4: Gen2<string> = { item: "hello" };  // ok
const gen5: Gen2<number> = { item: 2 };  // ok
const gen6: Gen2<boolean> = { item: true };  // error

関数

明示的に指定しなくても、型推論で定義される。

function funcGen<T>(props: T) {
  return { item: props };
}

const gen7 = funcGen("test");  // = const gen7 = funcGen<string>("test"); 

関数の場合のextends

function funcGen1<T extends string | null>(props: T) {
  return { value: props };
}

const gen8 = funcGen1("hello");  // ok
const gen9 = funcGen1(123);  // error

Props

interface Props {
  price: number;
}

function funcGen3<T extends Props>(props: T) {
  return { value: props.price };
}

const gen10 = funcGen3({ price: 1000 });   // ok
こまきちこまきち

JSON型推論

以下のようなJSONデータがあるとする

[{
  "id": 1,
  "first_name": "Jeanette",
  "last_name": "Penddreth",
  "email": "jpenddreth0@census.gov",
  "gender": "Female",
  "ip_address": "26.58.193.2"
}, {
  "id": 2,
  "first_name": "Giavani",
  "last_name": "Frediani",
  "email": "gfrediani1@senate.gov",
  "gender": "Male",
  "ip_address": "229.179.4.212"
}, {
  "id": 3,
  "first_name": "Noell",
  "last_name": "Bea",
  "email": "nbea2@imageshack.us",
  "gender": "Female",
  "ip_address": "180.66.162.255"
}

これをReactで読み込み、typeとして定義すると型推論される(!!!!)
最強か。

import Data from "./data.json";

type Users = typeof Data;
こまきちこまきち

React Hooks Props型

React v16.8からReact Hooksが追加されFunctional Componentベースの開発になったことから、それに対する型定義を学習する。
FC = Functional Component

App.tsx
const App: React.FC = () => {
  return (
     <div className="App">
       <header className="App-header">
         <TextComponent text="hello" />
       </header>
     </div>
  )
}
TestComponent.tsx
import React from "react";

interface Props {
  text: string;
}

// <Props>と指定することで、引数のpropsの型を定義することができる
const TestComponent: React.FC<Props> = (props) = {
  return (
    <div>
      <h1>{ props.text}</h1>
    </div>
  )
}
こまきちこまきち

React Hooks useState

TestComponent.tsx
import React, { useState } from "react";

interface Props {
  text: string;
}

const TestComponent: React.FC<Props> = (props) = {
  const [count, setCount] = useState(0);   // 型推論が行われ、引数がnumber型となる

  return (
    <div>
      <h1>{ props.text}</h1>
      <h1>{ count }</h1>
    </div>
  )
}

nullも受け付けるようにするには、以下のようにする

const [count, setCount] = useState<number | null>(0); 

オブジェクトを扱いたい場合

TestComponent.tsx
import React, { useState } from "react";

interface UserData {
  id: number;
  name: string;
}

const TestComponent: React.FC<Props> = (props) = {
  const [user, setUser] = useState<UserData>({ id: 1, name: "name" });

  return (
    <div>
      <h1>{ user.id }</h1>
      <h1>{ user.name }</h1>
    </div>
  )
}
こまきちこまきち

Event handlerのデータ型

ユーザがinput要素に何かを入力した際に、入力内容をwebに出力する。

TestComponent.tsx
import React, { useState } from "react";

interface UserData {
  id: number;
  name: string;
}

const TestComponent: React.FC<Props> = (props) = {
  const [unputData, setInputData] = useState("");

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => setInputData(e.target.value);

  return (
    <div>
      <input type="text" value={inputData} onChange={handleInputChange} />
      <h1>{inputData}</h1>
    </div>
  )
}
このスクラップは2022/06/13にクローズされました