feat(typescript-type-review): add W6 — nullable container redundancy (Alternative typeclass)
This commit is contained in:
parent
72af2ab3a1
commit
50ac98efba
@ -171,7 +171,50 @@ type SpawnError =
|
||||
| { kind: "spawn_failed"; message: string };
|
||||
```
|
||||
|
||||
#### W6: 宽泛类型参数
|
||||
#### W6: Nullable 容器冗余 — Alternative 类型的 `| null`
|
||||
|
||||
当一个类型自身就有"空"表示(Haskell 中称为 Alternative typeclass 的 `empty`),再包一层 `| null` 就引入了两种"没有"的语义,调用方必须同时处理两个分支,且很难分清它们的区别。
|
||||
|
||||
常见的 Alternative 类型:`T[]`(empty = `[]`)、`Record<string, T>`(empty = `{}`)、`Map<K,V>`、`Set<T>`、`string`(empty = `""`)。
|
||||
|
||||
**核心问题:`[]` 和 `null` 语义是否不同?如果相同,去掉 `| null`。**
|
||||
|
||||
```typescript
|
||||
// ❌ Bad — [] 和 null 都表示"没有标签",调用方要 if (tags === null || tags.length === 0)
|
||||
type Post = {
|
||||
tags: string[] | null;
|
||||
};
|
||||
|
||||
// ✅ Good — 空数组就是"没有"
|
||||
type Post = {
|
||||
tags: string[]; // empty array = no tags
|
||||
};
|
||||
```
|
||||
|
||||
```typescript
|
||||
// ❌ Bad — {} 和 null 都表示"没有 headers"
|
||||
type Request = {
|
||||
headers: Record<string, string> | null;
|
||||
};
|
||||
|
||||
// ✅ Good
|
||||
type Request = {
|
||||
headers: Record<string, string>; // empty object = no headers
|
||||
};
|
||||
```
|
||||
|
||||
**保留 `| null` 的合理场景**:当 `null` 和 empty 确实有不同业务语义时。例如:
|
||||
|
||||
```typescript
|
||||
// ✅ 这里 null = "从未加载过",[] = "加载了但结果为空"
|
||||
type SearchState = {
|
||||
results: SearchResult[] | null; // null = not yet searched
|
||||
};
|
||||
```
|
||||
|
||||
**审查方法**:每次看到 `T[] | null`、`Record<K,V> | null`、`Set<T> | null`、`Map<K,V> | null`、`string | null` 时,问一句:**empty 和 null 的语义是否不同?** 如果答不上来,去掉 `| null`。
|
||||
|
||||
#### W7: 宽泛类型参数
|
||||
`Record<string, unknown>` 或 `object` 通常意味着缺少具体类型定义。
|
||||
|
||||
```typescript
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user