Item 61: Use Record Types to Keep Values in Sync
要点
- Recognize the fail open versus fail closed dilemma.
- Use ++Record++ types to keep related values and types synchronized.
- Consider using ++Record++ types to force choices when adding new properties to an interface.
- 认识到“失败开放”(fail open)与“失败封闭”(fail closed)之间的两难问题。
- 使用
Record
类型来保持相关值和类型的同步。 - 在向接口添加新属性时,可以考虑使用
Record
类型来强制做出选择。
正文
ts
interface ScatterProps {
// The data
xs: number[]
ys: number[]
// Display
xRange: [number, number]
yRange: [number, number]
color: string
// Events
onClick?: (x: number, y: number, index: number) => void
}
ts
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
for (const kStr in oldProps) {
const k = kStr as keyof ScatterProps
if (oldProps[k] !== newProps[k]) {
if (k !== 'onClick') return true
}
}
return false
}
ts
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
return (
oldProps.xs !== newProps.xs ||
oldProps.ys !== newProps.ys ||
oldProps.xRange !== newProps.xRange ||
oldProps.yRange !== newProps.yRange ||
oldProps.color !== newProps.color
// (no check for onClick)
)
}
ts
interface ScatterProps {
xs: number[]
ys: number[]
// ...
onClick?: (x: number, y: number, index: number) => void
// Note: if you add a property here, update shouldUpdate!
}
ts
const REQUIRES_UPDATE: Record<keyof ScatterProps, boolean> = {
xs: true,
ys: true,
xRange: true,
yRange: true,
color: true,
onClick: false,
}
function shouldUpdate(oldProps: ScatterProps, newProps: ScatterProps) {
for (const kStr in oldProps) {
const k = kStr as keyof ScatterProps
if (oldProps[k] !== newProps[k] && REQUIRES_UPDATE[k]) {
return true
}
}
return false
}
ts
interface ScatterProps {
// ...
onDoubleClick?: () => void
}
ts
const REQUIRES_UPDATE: Record<keyof ScatterProps, boolean> = {
// ~~~~~~~~~~~~~~~ Property 'onDoubleClick' is missing in type ...
// ...
}
ts
const PROPS_REQUIRING_UPDATE: (keyof ScatterProps)[] = [
'xs',
'ys',
// ...
]