TypeScript条件类型能否实现Integer类型?
实现TypeScript编译时校验的Integer类型
问题分析
你之前编写的条件类型:
type Integer<T extends number> = `${T}` extends `${number}.${number}` ? never : T;
核心思路没问题——通过模板字面量将数值转为字符串,判断是否包含小数点来区分整数和小数。但它是泛型条件类型,必须传入具体的数值类型(比如Integer<5>)才能生效,直接用Integer作为变量类型时,泛型参数无法自动推断,因此只能约束特定整数,而非任意整数。
可行实现方案
TypeScript本身没有原生的整数类型,但可以通过以下方式结合条件类型实现编译时校验:
1. 泛型函数封装(推荐)
用泛型函数捕获赋值的数值,自动推断泛型参数并触发条件类型校验:
type Integer<T extends number> = `${T}` extends `${string}.${string}` ? never : T; function integer<T extends number>(value: Integer<T>): T { return value; } // 正常通过编译 const validInt = integer(123); const validNegInt = integer(-456); // 编译报错:类型“123.45”不能赋值给类型“never” const invalidFloat = integer(123.45); const invalidZeroFloat = integer(0.1);
2. 结合satisfies运算符(TS 4.9+)
如果不想用函数,可利用satisfies配合条件类型实现变量赋值时的校验:
type Integer<T extends number> = `${T}` extends `${string}.${string}` ? never : T; // 正常通过 const num1 = 789 satisfies Integer<789>; // 编译报错 const num2 = 789.1 satisfies Integer<789.1>;
3. 品牌类型(Brand Type)+ 运行时断言
如果需要同时兼顾编译时校验和运行时安全,可以结合品牌类型:
type Integer = number & { __brand: 'integer' }; function assertInteger<T extends number>(value: T): asserts value is Integer { if (!Number.isInteger(value)) { throw new Error(`Expected integer, got ${value}`); } } // 编译时允许赋值任意number,但调用assertInteger后会缩小类型 let num = 100; assertInteger(num); // 此时num的类型为Integer,赋值小数会编译报错 num = 200; // 正常 num = 200.5; // 编译错误
总结
可以通过条件类型实现需求,但需要结合泛型推断、函数封装或satisfies运算符来让条件类型作用于任意整数的赋值场景,而非仅特定数值。
内容的提问来源于stack exchange,提问作者ImpromptuMusic
相关产品推荐
相关产品推荐

