架构师Jack
1/12/2025
嘿,大家好!👋
最近我在折腾 TypeScript 的时候遇到了一个让我抓狂的问题。😩 我想创建一个 Example
类,类型是 Example<{ min: 1 }>
。一开始我觉得这应该很简单,但结果却让我大跌眼镜。
type Config = { min?: number; max?: number; }; class Example<C extends Config> { example = true; constructor(private config: Readonly<C> = {} as C) {} public min<const N extends number>(min: N) { return new Example<C & { min: N }>({ ...this.config, min, }); } }
我想要创建一个 Example
类的实例,类型是 Example<{ min: 1 }>
。
我写了一个 test
函数来测试各种构造类的方法:
const test = (example: Example<{ min: 1 }>) => example; // 这些应该可以工作 test(new Example({ min: 1 })); test(new Example().min(1)); test(new Example({}).min(1)); // 这些不应该工作 test(new Example({})); test(new Example({ min: 2 })); test(new Example().min(2));
一切都正常,直到我尝试了这个:
test(new Example());
居然没有报错!😱 默认的 {}
居然可以赋值给 { min: 1 }
,这不科学啊!
我试着修改 test
函数:
const test = <C extends { min: 1 }>(example: Example<C>) => example; test(new Example());
这样确实报错了,但这不是我想要的解决方案。问题是 new Example()
不应该能被赋值给 Example<{ min: 1 }>
。
我想要的是:
const example: Example<{ min: 1 }> = new Example();
这行代码应该报错才对。有没有大佬能帮我看看这个问题怎么解决?🙏
PS: 我在 TypeScript Playground 上也试过了,结果还是一样。真是让人头疼啊!😅
感谢大家的帮助!❤️
标签:TypeScript, 泛型, 类型检查, 默认参数
程序员老张
1/12/2025
嘿,你好啊!👋
我太理解你遇到的这个 TypeScript 类型问题了!我之前也在类型系统上栽过跟头,尤其是当涉及到复杂的泛型和类型约束时。别担心,我们一起来看看怎么解决这个问题吧。
你想要确保 Example<{ min: 1 }>
的严格类型检查,这意味着我们需要在类型系统中强制要求 min
属性的存在。为了实现这一点,我们可以利用 TypeScript 的条件类型和类型约束来确保类型的严格性。
我们可以通过修改 Example
类的构造函数来实现这一点。具体来说,我们可以在构造函数中添加一个类型约束,确保 min
属性存在:
type Config = { min?: number; max?: number; }; class Example<C extends Config> { example = true; constructor(private config: Readonly<C> & { min: number } = {} as C & { min: number }) {} public min<const N extends number>(min: N) { return new Example<C & { min: N }>({ ...this.config, min, }); } } // 测试函数 const test = (example: Example<{ min: 1 }>) => example; // 这些应该可以工作 test(new Example({ min: 1 })); test(new Example().min(1)); test(new Example({}).min(1)); // 这些不应该工作 test(new Example({})); // 现在会报错 test(new Example({ min: 2 })); // 现在会报错 test(new Example().min(2)); // 现在会报错
Readonly<C> & { min: number }
来确保 min
属性的存在。这意味着任何传递给 Example
的配置对象都必须至少包含一个 min
属性。as C & { min: number }
来强制类型转换,这样即使没有提供参数,类型系统也会要求 min
属性。as const
和条件类型来帮助调试复杂的类型问题。希望这些能帮到你!如果还有其他问题,随时问我哦!继续加油,TypeScript 的类型系统虽然复杂,但掌握之后会让你的代码更加健壮!💪
祝你好运!如果需要进一步的帮助,我随时在这儿!😊