教材の内容に関係のない質問や教材とは異なる環境・バージョンで進めている場合のエラーなど、教材に関係しない質問は推奨していないため回答できない場合がございます。
その場合、teratailなどの外部サイトを利用して質問することをおすすめします。教材の誤字脱字や追記・改善の要望は「文章の間違いや改善点の指摘」からお願いします。
TypeScript と JSX が JavaScript の拡張であることを理解し、基礎文法を習得します。
わからない文法を検索できるように、文法の名称を把握します。
今はこのパートをスキップして、あとから参照もできます。
TypeScript は、JavaScript に 静的型付け を持たせた上位言語です。
上位 とは、JavaScript で書かれたソースコードがすべて TypeScript として妥当であることを意味します。
JavaScript が書ければ TypeScript も書けることになるのです。
TypeScript にあって JavaScript にない文法は、型の宣言です。
ほかの文法は JavaScript にも存在します(現在の JavaScript に存在するとは限らないものの、少なくとも将来的な仕様や提案には含まれています)。
型の宣言は次のようなものです。
ts12345678910111213 Copied!// 変数宣言
const message: string = 'Hello'
// 引数と戻り値の型
function greet(message: string): void {
console.log(message)
}
// 独自型の定義
type Greeting = {
id: number
message: string
}
型は常に宣言する必要があるとは限りません。
TypeScript が強力に 推論 し、自動で型が決まるからです。
むしろ推論できるなら推論で型を決めたほうが、人為的ミスが減り好ましいでしょう。
次の例では、型の推論によって減算が型エラーとして検出されます。
JavaScript だけでは、実行してもエラーにならないため、検出できません。
ts12345678 Copied!// string 型に決まる
let a = '1'
// number 型に決まる
let b = 1
// string 型と number 型は減算できないので型エラー
console.log(a - b)
ブラウザーは JavaScript しか実行できないので、TypeScript で書いたソースコードは コンパイル(またはトランスパイル)によって JavaScript へ変換する必要があります。
この教材では、Parcel の内部の Babel というツールがトランスパイルを実行しています。
次の JSX 式は、h1
という JSX.Element を変数に代入するものです。
tsx1 Copied!const element = <h1 title="hello">Hello JSX!</h1>
このソースコードはコンパイルによって次の JavaScript コードへ変換されます。
js1 Copied!const element = React.createElement("h1", { title: "hello" }, "Hello JSX!");
element
は React.createElement
の戻り値なので、文字列ではありませんし、ほかの変数に代入したり関数の戻り値にしたりできる 普通の 値です。
TypeScript と JSX を組み合わせることで、React.createElement
の引数の型が検査できます。
つまり、次のことが型エラーとして検出できます。
h9
)を使っていないかtitle
は存在しているかtitle="hello"
は string 型かHello JSX!
を渡すことができるか、またその型は string 型でよいかTypeScript 固有の記法と JavaScript にもある記法を分けずに記載します。
記法 | 名称 | 説明 |
---|---|---|
const name = '' |
定数 | 定数宣言。できる限りこの記法を使う |
let name = '' |
変数 | 変数宣言。どうしても再代入したいときに使う。var は使わない |
() => {} |
アロー関数 | function() {} の別の書き方 |
const hello = () => {} |
アロー関数 | function hello() {} の別の書き方 |
name => {} |
アロー関数 | アロー関数の引数がひとつのときは括弧を省略できる |
name => name.trim() |
アロー関数 | name => { return name.trim() } と同じ意味 |
(async () => {})() |
即時実行関数式 (IIFE) | const func = async () => {}; func() と同じ意味 |
`Hello world!` |
テンプレート文字列 | 'Hello world!' と同じ意味。ただし改行も含められる |
`Hello ${name.trim()}!` |
テンプレート文字列 | 'Hello ' + name.trim() + '!' と同じ意味 |
const [, a, b] = arr |
分割代入 | const a = arr[1]; const b = arr[2] と同じ意味 |
const [, ...r] = arr |
分割代入 | arr の先頭の値以降を r という配列として取り出す |
const { a, b: b2 } = obj |
分割代入 | const a = obj.a; const b2 = obj.b と同じ意味 |
const { a, ...r } = obj |
分割代入 | obj の a 以外の値を r というオブジェクトとして取り出す |
function Hello({ name }) {} |
分割代入 | function Hello(args) { let { name } = args } と同じ意味 |
({ name }) => ({ name }) |
分割代入 | args => { let { name } = args; return { name } } と同じ意味 |
const n = [-1, ...arr, 2] |
スプレッド構文 | arr = [0, 1] の場合 n は [-1, 0, 1, 2] となる |
const n = { ...obj, z: 2 } |
スプレッド構文 | obj = { x: 0, y: 1 } の場合 n は { x: 0, y: 1, z: 2} となる |
const n = { a, b } |
オブジェクト初期化子 | const n = { a: a, b: b } と同じ意味 |
const name = input || 'default' |
OR 演算子 | input が null , undefined , '' のとき name === 'default' |
const name = input ?? 'default' |
Null 合体演算子 | input が null , undefined のとき name === 'default' |
const n = obj?.name |
Optional chaining | obj が null , undefined のときでもエラーにならない |
const n = arr?.[0] |
Optional chaining | arr が null , undefined のときでもエラーにならない |
func?.() |
Optional chaining | func が null , undefined のときでもエラーにならない |
const x = [0, 1] as const |
const assertions | 配列の中身を変更できないことを示す |
const x = { a: 'A' } as const |
const assertions | オブジェクトの中身を変更できないことを示す |
function fn(value: string) {} |
型アノテーション | 関数 fn が string 型の引数を受け取ることを明示する |
const name: string = '' |
型アノテーション | 定数 name が string 型であることを明示する |
const name = '' |
型推論 | 定数 name が string 型であることをコンパイラーが判断する |
function fn(): string {return ''} |
戻り値の型 | fn は string 型の値を返す関数 |
function fn(): void {} |
Void 型 | fn は値を何も(undefined や null すらも)返さない関数 |
type Name = string |
型のエイリアス | 型に別名をつける |
type Greeting = { name: string } |
型のエイリアス | 型に別名をつける |
type Q = typeof obj |
型クエリー | obj = { x: '' } のとき type Q = { x: string } と同じ意味 |
fn<string | undefined>(undefined) |
Type argument | 関数 fn に推論できない型があるとき、その型を明確にする |
{ name?: string } |
省略可能なプロパティ | 省略可能であることを示す |
type H = 'hello' |
文字列リテラル型 | 値が 'hello' である、制限の強い string 型 |
type I = { x: H } & { y: number } |
交差型 | { x: H } 型かつ { y: number } 型であるような型 |
type U = string | number |
共用体型 | string 型か number 型であることを示す |
const n = obj!.name |
Non-Null Assertion | obj が null , undefined のときでも 型エラー にならない。実行時エラーにはなりうる |
JSX 内で変数を使う
tsx12 Copied!const name = 'JSX'
const element = <h1>Hello {name}!</h1>
属性に固定の文字列以外の値を渡す
tsx12 Copied!const index = -1
const element = <h1 tabIndex={index}></h1>
if 文で条件分岐する
tsx1234567 Copied!function Hello({ name }) {
if (name) {
return <h1>Hello {name}!</h1>
}
return <h1>What's your name?</h1>
}
三項演算子で条件分岐する
tsx123456789 Copied!function Hello({ name }) {
return (
<div>
<h1>Hello!</h1>
{name ? <p>Your name is {name}</p> : <p>Mr. Anonymous</p>}
</div>
)
}
AND 演算子で条件分岐する
tsx123456789 Copied!function Hello({ name }) {
return (
<div>
<h1>Hello!</h1>
{name && <p>Your name is {name}</p>}
</div>
)
}
要素を繰り返す
tsx123456789101112131415 Copied!const people = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 20 },
]
const element = (
<div>
{people.map(({ name, age }) => (
<p key={name}>
<b>Name: {name}</b>
<span>Age: {age}</span>
</p>
))}
</div>
)
特殊な React.Fragment
コンポーネントを使う
tsx1234567891011121314 Copied!function Hello({ name }) {
return (
<div>
{name ? (
<>
<h1>Hello!</h1>
<p>Your name is {name}</p>
</>
) : (
<p>What's your name?</p>
)}
</div>
)
}
このパートは以上です。おつかれさまでした。