Open7
TypeScript Tips
EventTarget
を HTMLElement
として型安全に扱う
EventTarget
は window
や document
を含むので、絞り込む必要がある。
export class AnchorOver {
private targets: HTMLAnchorElement[]
constructor() {
this.targets = [...document.querySelectorAll('a')].filter(
(item) => item.dataset.color,
)
this.overHandle = this.overHandle.bind(this)
}
start() {
this.targets.forEach((el) => {
el.addEventListener('mouseenter', this.overHandle)
})
}
overHandle({ target }: MouseEvent) {
if (!(target instanceof HTMLAnchorElement)) return
console.log('🖱 mouseenter', target && target.dataset)
}
}
keyof
typeof
で 取り出した key でオブジェクトを型定義
外部から参照用に定義したas const
なオブジェクトから、 keyof
typeof
で key を取り出して、オブジェクトの型定義をする。
export const values = {
x: 'x',
y: 'y',
z: 'z'
} as const
type Keys = keyof typeof values;
type Flags = { [K in Keys]: boolean };
const flag: Flags = {
x: true,
y: false,
z true
}
Parameters
Parameters<Func>
は、あたえた関数の引数の型を配列で返してくれる。
type MemberType = Parameters<(name: string, age: number) => void>
const luffy: MemberType = ['Luffy', 21]
type EventParamType = Parameters<typeof addEventListener>
const prams: EventParamType = [
'click',
(event) => {
console.log(event.target)
}
]
addEventListener(...prams)
Record
Record<key, type>
でオブジェクトの型を表現する。
type MemberInfo = {
age: number
fullName: string
}
type MemberName = 'luffy' | 'nami' | 'zoro'
const MugiwaraPirates: Record<MemberName, MemberInfo> = {
luffy: { age: 21, fullName: 'Monkey D. Luffy' },
nami: { age: 21, fullName: 'Nami' },
zoro: { age: 22, fullName: 'Roronoa Zoro' }
}
シンプルな使い方
const age: Record<string, number> = {}
age.luffy = 21
age.zoro = 22
デフォルト型引数
型TをErrorのサブクラスに限定しつつ、省略時はSyntaxErrorとしたい場合。
type MyErrorEvent<T extends Error = SyntaxError> = {
error: T;
type: string;
};
window.navigator['userAgentData']
の型をつける
type Brand = {
readonly brand: string;
readonly version: string;
};
type NavigatorUAData = {
readonly brands: Brand[];
readonly mobile: boolean;
readonly platform: string;
};
declare global {
interface Navigator {
userAgentData: NavigatorUAData;
}
}
オプショナルなオブジェクトのメンバーのどれかひとつが少なくとも含まれる型を定義する
type RequireOne<T, K extends keyof T = keyof T> =
K extends keyof T ? PartialRequire<T, K> : never
type PartialRequire<O, K extends keyof O> = {
[P in K]-?: O[P]
} & O
const sizeNames = ['s', 'm', 'l'] as const
type Size = typeof sizeNames[number]
type SizeOptions = RequireOne<{
[k in Size]?: number
}>
const optA: SizeOptions = {s: 100}
// error
const optB: Options = {}