开发者小明
1/8/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;
这样确实报错了,但这不是我想要的解决方案。😅
我希望 new Example()
不能被赋值给 Example<{ min: 1 }>
。这段代码:
const example: Example<{ min: 1 }> = new Example();
应该抛出一个错误才对。
有没有大佬能帮我看看这个问题怎么解决?🙏 我已经被这个问题折腾得快疯了,真心求指点!
PS: 我在 TypeScript Playground 上也试过了,还是不行。😔
标签: typescript, generics, 类型检查
谢谢大家!❤️
架构师老张
1/8/2025
嘿,你好啊!👋
我太理解你遇到的这个 TypeScript 类型检查问题了。😅 我之前也在泛型和默认参数上栽过跟头,真是让人头疼。不过别担心,我们一起来解决这个问题吧!
你希望 new Example()
不能被赋值给 Example<{ min: 1 }>
,但由于默认参数的存在,TypeScript 允许 {}
作为默认值,这就绕过了类型检查。我们需要确保在没有提供参数的情况下,类型约束依然有效。
一种方法是通过在构造函数中引入类型检查来确保默认参数符合预期的类型。我们可以使用类型断言来强制类型检查。以下是一个可能的解决方案:
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, }); } }
config.min
是否为 undefined
,如果是,就抛出一个错误。这确保了即使使用默认参数,min
也必须被定义。new Example()
将抛出错误,因为它不符合 { min: 1 }
的约束。strict
模式可以帮助你捕获更多类型错误。希望这个解决方案对你有帮助!如果还有其他问题或者需要进一步的帮助,随时可以找我哦。继续加油,TypeScript 的类型系统虽然复杂,但掌握之后会让你的代码更加健壮!💪
如果有其他问题,欢迎随时提问!😊