全栈老张
1/8/2025
嘿,大家好!👋
最近我在折腾 TypeScript 的时候遇到了一个让我抓狂的问题。😵💫 我在用泛型和默认参数的时候,发现默认参数居然绕过了泛型类型检查!这让我有点懵逼,因为我本来以为 TypeScript 会帮我守住类型的边界。
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;
这样一来,测试就报错了,但这不是我想要的解决方案。🤔
我想知道如何让 new Example()
不能被赋值给 Example<{ min: 1 }>
。有没有大佬能帮我看看这个问题?🙏
PS: 我在 TypeScript Playground 上也试过了,结果还是一样。链接在这:Playground
谢谢大家的帮助!💡
架构师小明
1/8/2025
好啊!👋
我太理解你遇到的这个 TypeScript 泛型和默认参数的问题了!我之前也在这上面栽过跟头,真是让人抓狂。😅
你遇到的问题是因为 TypeScript 的默认参数机制。默认参数在某些情况下会绕过类型检查,因为 TypeScript 会认为默认值是一个有效的初始值,而不去严格检查它是否符合泛型约束。
为了确保 new Example()
不能被赋值给 Example<{ min: 1 }>
,我们可以通过在构造函数中添加类型检查来解决这个问题。具体来说,我们可以在构造函数中使用类型断言来确保传入的配置符合泛型约束。
type Config = { min?: number; max?: number; }; class Example<C extends Config> { example = true; constructor(private config: Readonly<C> = {} as C) { // 添加类型检查 if (config.min === undefined) { throw new Error("Config must have a 'min' property"); } } 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));
在这个解决方案中,我们在构造函数中添加了一个简单的检查,确保 config
中必须有 min
属性。这样一来,当你调用 new Example()
时,如果没有提供 min
属性,就会抛出一个错误,从而防止不符合类型约束的实例被创建。
as
断言来帮助调试类型问题,但要小心使用,避免过度依赖。希望这个解决方案能帮到你!如果还有其他问题,随时来问哦,我很乐意继续帮助你。加油!🚀
如果你有其他的 TypeScript 问题或者想要更深入的讨论,随时欢迎!😊