Item 42: Avoid Types Based on Anecdotal Data
要点
- Avoid writing types by hand based on data that you've seen. It's easy to misunderstand a schema or get nullability wrong.
- Prefer types sourced from official clients or the community. If these don't exist, generate TypeScript types from schemas.
- 避免根据你所看到的数据手动编写类型。误解 schema 或错误处理 nullability 是很容易的。
- 优先使用官方客户端或社区提供的类型。如果没有这些,考虑从 schema 生成 TypeScript 类型。
正文
ts
function calculateBoundingBox(f: GeoJSONFeature): BoundingBox | null {
let box: BoundingBox | null = null
const helper = (coords: any[]) => {
// ...
}
const { geometry } = f
if (geometry) {
helper(geometry.coordinates)
}
return box
}
ts
interface GeoJSONFeature {
type: 'Feature'
geometry: GeoJSONGeometry | null
properties: unknown
}
interface GeoJSONGeometry {
type: 'Point' | 'LineString' | 'Polygon' | 'MultiPolygon'
coordinates: number[] | number[][] | number[][][] | number[][][][]
}
ts
import { Feature } from 'geojson'
function calculateBoundingBox(f: Feature): BoundingBox | null {
let box: BoundingBox | null = null
const helper = (coords: any[]) => {
// ...
}
const { geometry } = f
if (geometry) {
helper(geometry.coordinates)
// ~~~~~~~~~~~
// Property 'coordinates' does not exist on type 'Geometry'
// Property 'coordinates' does not exist on type 'GeometryCollection'
}
return box
}
ts
const { geometry } = f
if (geometry) {
if (geometry.type === 'GeometryCollection') {
throw new Error('GeometryCollections are not supported.')
}
helper(geometry.coordinates) // OK
}
ts
const geometryHelper = (g: Geometry) => {
if (g.type === 'GeometryCollection') {
g.geometries.forEach(geometryHelper)
} else {
helper(g.coordinates) // OK
}
}
const { geometry } = f
if (geometry) {
geometryHelper(geometry)
}