功能说明
该示例提供一组类型级断言工具,让类型行为也进入测试范围。Equal 判断两个类型是否完全相同,Expect 要求条件必须为 true,IsAny 检测 any,TypeAssertions 把多条断言集中在一起。只要有一条不满足,tsc 就会报错,从而在 CI 中阻止类型回归。它还提供两个零成本的运行时助手,方便在测试代码中表达期望。
关键代码
Equal 使用经典的函数参数逆变技巧,用两个只在条件类型上不同的泛型函数互相赋值,从而区分 any、unknown、联合类型顺序与可选修饰符。Expect 的泛型约束为 true,传入 false 会直接编译失败。IsAny 利用 0 extends 1 与 any 的交叉结果为 any 的特性。expectType 原样返回参数以保留字面量类型,expectAssignable 只检查可赋值性。
使用注意
类型断言只有在 tsc 或 astro check 真正执行时才有意义,纯运行时测试不会触发。Equal 对 readonly 修饰符敏感,写断言时要确认期望的精确形状。expectType 不是严格相等断言,它只约束参数可赋值给 Expected,需要精确比较时仍应使用 Equal。不要在生产代码中保留大量测试类型,可放入单独的测试文件并由 tsconfig 包含。
验证方式
在 TypeAssertions 中放置 string 与 string、unknown 的 IsAny 为 false、any 的 IsAny 为 true、联合顺序无关等断言,运行 tsc 应通过。故意把一条改成 false,确认 tsc 报类型不满足约束。运行示例确认 expectType 返回原对象、expectAssignable 接受联合类型中的两种值。
代码示例
export type Equal<Left, Right> =
(<Value>() => Value extends Left ? 1 : 2) extends <Value>() => Value extends Right ? 1 : 2
? true
: false;
export type Expect<Condition extends true> = Condition;
export type IsAny<Value> = 0 extends 1 & Value ? true : false;
export function expectType<Expected>(value: Expected): Expected {
return value;
}
export function expectAssignable<Expected>(value: Expected): void {
void value;
}
export type TypeAssertions = [
Expect<Equal<string, string>>,
Expect<Equal<IsAny<unknown>, false>>,
Expect<Equal<IsAny<any>, true>>,
Expect<Equal<"a" | "b", "b" | "a">>,
Expect<Equal<{ id: number }, { id: number }>>,
];
const user = expectType<{ id: number }>({ id: 1 });
console.log(user.id);
expectAssignable<string | number>("ok");
expectAssignable<string | number>(42);