実践TypeScript 吉井 健文 (著) を読んでわからなかったことをメモしておくところ
declare
って毎回書いてあるけど、これはなに? (本文にはない)
🤔 生成した型定義ファイルでに declare function getPriceLabel(amount: number, tax: number): string;
🔎
「JavaScriptのライブラリは色々な種類がある
そのそれぞれの種類でうまいことやるように declare つけてる」 であってるかな?
🤔 3-5-1 でエラーが表示されて tsc
実行できない。
error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the
lib compiler option to es2015 or later.
target library ってどの library のことだろう。
非同期処理を行うためのPromiseはEMCAScript 2015で仕様に追加されたので、tsconfig.json
のtargetLibrary をes2015
以降にして tsc
する必要があったというだけだった。
🛡 Type guard 🛡
function greet(name?: string) {
if (name == undefined) return "Hello" // Type Guard
return `Hello ${name.toUpperCase()}`
}
console.log(greet())
console.log(greet("taro"))
Excess Property Checks
変数を渡すのとオブジェクトリテラルを引数に直接記述するのとで挙動が変わる
やばくない・・・?
関数呼び出し時に直接呼ぶのが設定値を渡すシーンで多く使われるので、「あんたこれ設定にない値だけど大丈夫なの?」という感じで過剰に検査するようになっているとのこと。
初見殺し‥
type User = {
age?: number,
name?: string,
}
const notUser = {
gender: "male",
graduate: "Tokyo"
}
const maybeUser = {
age: 26,
name: "taro",
gender: "male"
}
function registerUser(user: User) { }
// registerUser(notUser) エラーになる。これはわかる。
registerUser(maybeUser)
// 同じ内容だけど直接値を渡すとエラーになる。初見殺し。
// registerUser(
// {
// age: 26,
// name: "taro",
// gender: "male"
// }
// )
... っていうオブジェクトスプレッドというのを使うと変数を使うときと同じでエラーにならない。なんだと。。。
registerUser(
{
...
{
age: 26,
name: "taro",
gender: "male"
}
}
)
🔝 トップレベルプロパティ 🔝
インデックスシグネチャのnumberとstringに互換性がないため。
type User1 = {
name: string // <- エラーになる
[k: string]: number
}
const userA: User1 = {
name: "Taro",
age: 26
}
[k: string]: number | string
インデックスシグネチャの型を Union Types にする。
type User1 = {
name: string // <- エラーにならない
[k: string]: number | string // <- インデックスシグネチャの型を Union Types に
}
const userA: User1 = {
name: "Taro",
age: 26
}
リスト4-2-15実行時のエラー
interface User15 {
[k: string]: any
}
const user15: User15 = {
name: "Taro",
age: 28,
walk: () => { },
talk: async () => { },
}
An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your
--lib
option.ts(2705)
interface User16 {
[k: string]: Promise<any>
}
const user16: User16 = {
// name: "Taro",
// age: 28,
// walk: () => { },
talk: async () => { }
}
src/4-2/4-2-16.ts:9:9 - error TS2739: Type '() => Promise<void>' is missing the following properties from type 'Promise<any>': then, catch, [Symbol.toStringTag]
9 talk: async () => { }
~~~~~~~~~~~~~~~
src/4-2/4-2-16.ts:9:9
9 talk: async () => { }
~~~~~~~~~~~~~~~
Did you mean to call this expression?
Found 1 error.
tsconfigでは "target": "ES2015"
を指定。
解決
interface でも関数だよーってことを書いてあげないといけなかった
interface User16 {
[k: string]: () => Promise<any> // 🈁
}
const user16: User16 = {
// name: "Taro",
// age: 28,
// walk: () => { },
talk: async () => {}
}
function greet23(): any {
console.log("hello")
}
const message23 = greet23()
console.log(message23.toUpperCase())
返り値がないのにtoUpperCaseをよんでるけどエラー出てない。
実行すると…ランタイムエラー
any を指定したことで戻り値がないよを示すvoidが相殺されていた。anyを付与しなければエラーが出てくれる。
function greet23() {
console.log("hello")
}
const message23 = greet23()
// console.log(message23.toUpperCase()) エラーになってくれる
⚠️ Non-null assertion
null および undefined ではない状況が信頼できない限り使わない。
5-1-4 クラスの互換性、全然理解できなかった・・・後で復習する
5章 {}型
の読み方について社内の神に聞いたところ、
普段だったら オブジェクト型 と読む
でも、TS だと object 型 も存在する
TS文脈だったら、オブジェクトリテラル型が良さそう
との神回答を頂いた
interface
は open ended に準拠しているので、型拡張ができる。
type alias
はよくみる type User = {name: string} みたいなやつ。
Express
は Node.js のウェブサーバー
ReactとTypeScriptを一緒に使うことで、末端まで型をチェックできるから、修正による考慮外の挙動を減らせる。一緒に使うメリット。