TS 를 ES5 로 내리면 Error 를 상속한 클래스의 instanceof 가 깨진다 — super() 직후 프로토타입을 직접 맞춘다. ES2015 이상 타깃이면 필요 없다.1

class CustomError extends Error {
  name = 'CustomError'

  constructor(message?: string) {
    super(message)

    Object.setPrototypeOf(this, CustomError.prototype)
  }
}

try {
  throw new CustomError('This is a custom error message.')
} catch (error) {
  if (error instanceof CustomError) {
    console.log('CustomError occurred:', error.message)
    console.log('Error name:', error.name)
  } else {
    console.log('An error occurred:', error)
  }
}

Footnotes

  1. TypeScript Breaking Changes — TypeScript 2.1: “constructor functions for Error, Array, and the like use ECMAScript 6’s new.target to adjust the prototype chain; however, there is no way to ensure a value for new.target when invoking a constructor in ECMAScript 5.” / “As a recommendation, you can manually adjust the prototype immediately after any super(...) calls.” ↩

#287

A practical functional library for JavaScript programmers.



Footnotes

  1. 자바스크립트에서 객체는 항상 참조를 통해 전달되므로 전달된 객체는 안전하지 않은 문제가 있어서 함수형 프로그래밍을 도입하고 ramda를 이용해서 읽기 쉽고 유지 관리하기 쉬운 코드를 작성한 예를 보여주고 있다. ↩

#285

A toolkit for building rich-text editors on the web




Footnotes

  1. NYT 편집기 Oak 팀이 React 와 ProseMirror 를 붙이다 겪은 문제와 해법. React 는 render → commit 2단계, ProseMirror 는 동기로 한 번에 DOM 을 고치고 브라우저 편집을 읽어 들이는 양방향이라, useLayoutEffect 로 view.updateState() 하면 좌표가 낡고 state tearing 이 난다. 결국 EditorView 를 상속해 setProps 를 부수효과 없는 pureSetProps 와 runPendingEffects 로 쪼개고 렌더러를 React 로 다시 썼다 (@handlewithcare/react-prosemirror). ↩

  2. Oak 팀 교육 자료. ProseMirror 를 Redux + React 에 대응시킨다 — EditorView = store, transaction = action(대부분 ProseMirror 가 입력에서 만든다), plugin = reducer 확장·subscribe, dispatchTransaction = middleware, node spec 의 toDOM = 컴포넌트(0 이 children 자리). ↩

#284

process.env 를 스키마로 parse 하면 빠진 값은 시작할 때 ZodError 로 터지고1, 결과에는 선언한 키만 남는다2.

import z from 'zod'

const envSchema = z.object({
  REACT_APP_FEATURE_VAC_ASK: z.string(),
  REACT_APP_FEATURE_RECORDS: z.string(),
  NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
})

const windowSchema = z.object({
   SOMETHING_COOL: z.string()
})

export const ENV = envSchema.parse(process.env)
export const WINDOW = windowSchema.parse(window)

Footnotes

  1. Basic usage | Zod: “When validation fails, the .parse() method will throw a ZodError instance with granular information about the validation issues.” ↩

  2. Defining schemas | Zod: “By default, unrecognized keys are stripped from the parsed result” ↩

#280
type Props = {
  popover: 'auto' | 'hint' | 'manual'
  popovertarget: string
  popovertargetaction: 'hide' | 'show' | 'toggle'
}

type State = {
  hasBackdrop: boolean // CSS ::backdrop
  isPopoverOpen: boolean // CSS :popover-open
}

type Methods = {
  hidePopover: () => void
  showPopover: () => void
  togglePopover: () => void
}

type Events = {
  beforetoggle: () => void
  toggle: () => void
}

#279

zodios는 ZodError를 ZodiosError.cause에 담아 던진다1 — instanceof z.ZodError로는 안 잡힌다.

if (err instanceof ZodiosError && err.cause instanceof ZodError) {
  console.log(fromZodError(err.cause).toString())
}

Footnotes

  1. zodios zod-validation.plugin.ts: 응답 검증 실패 시 throw new ZodiosError(… config, response.data, parsed.error) — 네 번째 인자가 cause다. ↩

#278

올린 뒤 배포물에서 지운다 — Datadog은 이미 받았고1 브라우저에는 노출되지 않는다.

VERSION=$(git log --pretty=format:'%h' -n 1)

yarn datadog-ci sourcemaps upload ./build \
  --service "$SERVICE" \
  --minified-path-prefix "$MINIFIED_PATH_PREFIX" \
  --release-version "$VERSION"

rm ./build/static/js/*.map

Footnotes

  1. Upload JavaScript Source Maps - Datadog: “It scans the dist directory and subdirectories to automatically upload source maps with the relevant minified files.” ↩

#276

버스 팩터 — 한꺼번에 빠지면 프로젝트가 멈추는 최소 인원 수. 1이면 그 사람이 곧 단일 장애점.

#274

스택 = 서로 의존하는 PR의 연쇄. 기능 브랜치는 main에서 분기하지만 스택은 부모 PR에서 분기한다 — 그래서 검토를 기다리는 동안 다음 조각을 이어서 작업할 수 있다.

병합은 스택 아래부터. 하나가 병합되면 그 위 PR의 base를 갱신해야 한다. git 기본 기능만으로도 되지만 리베이스가 계속 따라붙어서, Graphite·Sapling 같은 도구가 그 부분을 자동화한다.

#272
33 중 18페이지