Open13

TypeScriptの型

10000leaves10000leaves

そもそもTypeScriptとは

TypeScriptとは、JavaScriptがベースとなっており変数や引数などに対して型(数値や文字型など)を付けることができる言語。

変数や関数の後に「」を付け、その後に任意の型を書く必要がある。

10000leaves10000leaves

プリミティブ型 (primitive types)

基本的な型

// 文字列:string
let str: string = 'hello world';

// 数値:number
let num: number = 123;

// 大きい数値: bigint
let bignum: bigint = 1235467891234567n;

// 真偽値:boolean
let bool: boolean = true;

// 空の値:null
let n: null = null;

// 未定義の値:undefined
let ud: undefined = undefined

// 一意のデータ:symbol
let sym: symbol = symbol()
10000leaves10000leaves

ユニオン型 (union type)

「いずれかの型」を表現するもの。
パイプ(こういうやつ⇒ | )で区切ることで、1つの要素に対して複数の型をつける。

// 文字列と数値を代入できる変数 ※es2020以降
let str_num: string | number

str_num = 'こんにちは'
console.log(str_num) // こんにちは

str_num = 123
console.log(str_num) // 123
10000leaves10000leaves

リテラル型 (literal type)

プリミティブ型の特定の値だけを代入可能にする型。
もうこのデータしか受け付けません!!みたいなこと。

// Helloしか代入できない
let x: 1;
x = 1;
x = 100;
Type '100' is not assignable to type '1'.
10000leaves10000leaves

配列型 (array type)

型名の後に[]を付けて宣言すると、その型しか挿入できない型ができる。
また、ユニオン型を使って複数の型が入る配列もできる。

// 数値の配列
let nums: number[] = [1,2,3];

// 文字列の型
let strs: string[] = ['a','b','c'];

// 色々な型の配列
let some: (string | number | boolean)[] = [1,'Hello',true];
10000leaves10000leaves

オブジェクト型 (object type)

オブジェクトの形式で1つのプロパティに対して自由に型を宣言できる。

基本的にオブジェクト型に代入する値は宣言したプロパティの数だけデータを入れないとエラーになる。

// 名前と年齢のオブジェクトを指定する型
let userData: { name: string, age: number } = {
	name: 'aaa',
	age: 20
}

データ入れたくない場合

データ入れたくない場合はプロパティの後に「?」を付ける。

// エラーになる
let userData: { name: string, age: number, profile: string } = {
	name: 'aaa',
	age: 20,
}

// ↓

// エラーにならない
let userData: { name: string, age: number, profile?: string } = {
	name: 'aaa',
	age: 20,
}
10000leaves10000leaves

関数の型の宣言 (function type declaration)

TypeScriptで関数を作成する際は、引数や戻り値にも型定義をする必要がある。
引数は引数の後に型を定義し、戻り値は引数のカッコの後に型を定義します。

// 関数の型宣言構文
type 型の名前 = (引数名: 引数の型) => 戻り値の型;

// 関数の定義
function sum(a: number, b: number): number{
	return a + b;
}

// アロー関数
const sum = (a: number, b: number): number => x + y;

// デフォルトの値も設定可能で、引数が渡らなくても計算可能になります。
function sum2(a: number b: number = 1): number{
	return a + b;
}

console.log(sum2(5)) // 6

// 戻り値が無い関数の場合はvoidを指定します。
const greet = (text: string): void => console.log(text)

簡略化

// 関数の型定義
type SumType = (a: number, b: number) => number

const sum: SumType = (a,b) => a + b;
10000leaves10000leaves

ジェネリクス (generics)

主に関数の定義の時に使用され、型を関数使用時に自由に決められるようになる機能。
型も引数のように扱い、共通化できる。

// <>の中に型の情報が入る。
const arrGenerator = <T>(value: T, time: number): T[]{
	return new Array(time).fill(value) // 配列をvalueのデータで埋め尽くす
}

console.log(arrGenerator<number>(1, 3)) //[1,1,1]
console.log(arrGenerator<string>('foo', 3)) //['foo','foo','foo']
10000leaves10000leaves

コンポーネントの定義 (component)

//---------------------------------コンポーネント
const Hello: React.FC = () => {
	return <h1>Hello Workd!!</h1>
}
export default Hello

//---------------------------------コンポーネントを利用
import Hello from './Hello'

const App: React.FC = () => {
	return <Hello />
}
export default App
10000leaves10000leaves

propsの定義

//---------------------------------コンポーネント
// propsの型
type Props = {
	greet: string
}

// コンポーネント作成
const Hello: React.FC<Props> = (props) => {
	return <h1>Hello {props.greet}</h1>
}
export default Hello

//---------------------------------コンポーネント利用
import Hello from './Hello'

const App: React.FC = () => {
	return <Hello greet='World!!!'>
}
export default App

Childrenを定義

Childrenを定義する場合はReact.ReactNodeを定義。

//---------------------------------コンポーネント
// propsの型
type Props = {
	greet: string,
	children: React.ReactNode
}

// コンポーネント作成
const Hello: React.FC<Props> = (props) => {
	return (
		<>
			<h1>Hello { props.greet }</h1>
			<div>{ props.children }</div>
		</>
	)
}
export default Hello

//---------------------------------コンポーネント利用
import Hello from './Hello'

const App: React.FC = () => {
	return <Hello greet='World!!!'>Its A My World!!!</Hello>
}
export default App //<h1>Hello World!!!</h1><div>Its A My World!!!</div>

関数を渡す

//---------------------------------コンポーネント
// propsの型
type Props = {
	func: () => void
}

// コンポーネント作成
const Btn: React.FC<Props> = (props) => {
	return <button onClick={ () => props.func }>ボタン</button>
}
export default Btn

//---------------------------------コンポーネント利用
import Btn from './Btn'

const App: React.FC = () => {
	const greet = () => console.log("Hello World!!!")
	return <Btn func={ greet } />
}
export default App
10000leaves10000leaves

イベントの型定義

コンポーネント内でボタンのクリックイベントやselectタグのチェンジイベントの処理を分けて記述するときは、React専用のイベント型を定義する必要がある。

const App = () => {
    // クリックイベントの定義
    const handleClick = (event: React.MouseEvent<HTMLButtonElement,MouseEvent>) => {
        console.log("Hello World")
    }

    return (
        <>
            <button onClick={handleClick}>ボタン</button>
        </>
    )
}

クリックイベントの以外のイベント型

onClick: (event: React.MouseEvent<HTMLInputElement>) => void // クリックイベント 
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void // チェンジイベント 
onkeypress: (event: React.KeyboardEvent<HTMLInputElement>) => void // キーボードイベント 
onBlur: (event: React.FocusEvent<HTMLInputElement>) => void // 要素のフォーカスが外れた時
onFocus: (event: React.FocusEvent<HTMLInputElement>) => void // 要素のフォーカス時のイベント 
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void // formのsubmit時のイベント 
10000leaves10000leaves

stateの型定義

// stateの定義
const [ state, setState ] = useState<string>('Hello')

// 型エイリアスを利用することもできる
type Users = {
	name: string,
	age: number
}

const [ users, setUsers ] = useState<Users[]>([
	{ name: 'Taro', age: 20 },
	{ name: 'Jiro', age: 17 }
])