Open7

TypeScript Tips

uto-usuiuto-usui

EventTargetHTMLElement として型安全に扱う

EventTargetwindowdocument を含むので、絞り込む必要がある。

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)
  }
}
uto-usuiuto-usui

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
}
uto-usuiuto-usui

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)
uto-usuiuto-usui

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
uto-usuiuto-usui

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;
  }
}
uto-usuiuto-usui

オプショナルなオブジェクトのメンバーのどれかひとつが少なくとも含まれる型を定義する

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 = {}

https://qiita.com/uhyo/items/583ddf7af3b489d5e8e9