打字稿在索引签名后推断原始对象类型
typescript infer raw object type after index signature
假设我有对象:
const styles = { product: { color: 'blue' } };
由此推断出对象类型,我可以毫无问题地访问 foo.bar.baz
。
但是,如果我想要进行类型检查,我需要这样的东西:
import type CSS from 'csstype';
type StyleSheet = Record<string,CSS.Properties>;
const styles:StyleSheet = {
product: { color: 'blue' }
};
上面的内容是有效的,但是,当访问 styles
时,我会得到定义的 styles.whatever.color
或 styles.product.margin
,这是不希望的。
考虑到这一点,Typescript 中是否有任何方法可以在键入对象后推断对象的原始类型,以便我可以访问其真实属性,如下所示:
const styles:StyleSheet = { product: { color: 'blue' } }; // typed as 'StyleSheet' so I get type-checking
styles.whatever.margin // TS thinks this is valid because of the index signature;
const original = styles as OriginalObject; // infer original type so only real properties are accessible
original.whatever // invalid (expected)
original.product.color // valid
export default original;
更新
回复@jcalx 的:
你想检查 styles
是一个 StyleSheet
没有 扩大 styles
到 StyleSheet
并且让编译器忘记关于它的个别属性。
一种方法是让编译器推断 styles
的类型,并相信 TypeScript 的结构类型系统会在您不喜欢的地方使用它时发出警告。也就是说,假设您有一些需要 StyleSheet
:
的函数
function someFunctionThatNeedsAStyleSheet(s: StyleSheet) { }
您可以只制作一些未注释的对象:
const styles = { product: { color: 'gray' } };
const badStyles = { product: { colour: 'grey' } };
编译器会记住它们的属性:
styles.whatever.margin // error;
styles.product.color // okay
稍后,当您将它们传递给函数时,它会接受它或警告您:
someFunctionThatNeedsAStyleSheet(styles); // okay
someFunctionThatNeedsAStyleSheet(badStyles); // error!
// ----------------------------> ~~~~~~~~~
// Type '{ colour: string; }' has no properties in common
// with type 'Properties<string | 0>'
你做在这里进行类型检查。但当然,它不在您声明 styles
变量的同一位置。
如果你想在创建错误的 StyleSheet
时立即捕获它,你可以通过创建这样的辅助函数来使用上述类型检查函数的想法:
const asStyleSheet = <T extends StyleSheet>(t: T) => t;
函数asStyleSheet()
是一个通用的身份函数:它returns它的输入,与输入的类型相同。但是泛型是constrained到StyleSheet
,所以传错了就会报错。像这样:
const styles = asStyleSheet({ product: { color: 'gray' } }); // okay
const badStyles = asStyleSheet({ product: { colour: 'grey' } }) // error!
// ---------------------------------------> ~~~~~~~~~~~~~~
// 'colour' does not exist in type 'Properties<string | 0>'.
// Did you mean to write 'color' ?
通过使用 asStyleSheet()
,您正在检查 styles
的类型而不更改它; asStyleSheet()
的输出与输入的类型相同。所以编译器记住它的属性:
styles.whatever.margin // error;
styles.product.color // okay
看起来不错。
好的,希望对您有所帮助;祝你好运!
假设我有对象:
const styles = { product: { color: 'blue' } };
由此推断出对象类型,我可以毫无问题地访问 foo.bar.baz
。
但是,如果我想要进行类型检查,我需要这样的东西:
import type CSS from 'csstype';
type StyleSheet = Record<string,CSS.Properties>;
const styles:StyleSheet = {
product: { color: 'blue' }
};
上面的内容是有效的,但是,当访问 styles
时,我会得到定义的 styles.whatever.color
或 styles.product.margin
,这是不希望的。
考虑到这一点,Typescript 中是否有任何方法可以在键入对象后推断对象的原始类型,以便我可以访问其真实属性,如下所示:
const styles:StyleSheet = { product: { color: 'blue' } }; // typed as 'StyleSheet' so I get type-checking
styles.whatever.margin // TS thinks this is valid because of the index signature;
const original = styles as OriginalObject; // infer original type so only real properties are accessible
original.whatever // invalid (expected)
original.product.color // valid
export default original;
更新
回复@jcalx 的:
你想检查 styles
是一个 StyleSheet
没有 扩大 styles
到 StyleSheet
并且让编译器忘记关于它的个别属性。
一种方法是让编译器推断 styles
的类型,并相信 TypeScript 的结构类型系统会在您不喜欢的地方使用它时发出警告。也就是说,假设您有一些需要 StyleSheet
:
function someFunctionThatNeedsAStyleSheet(s: StyleSheet) { }
您可以只制作一些未注释的对象:
const styles = { product: { color: 'gray' } };
const badStyles = { product: { colour: 'grey' } };
编译器会记住它们的属性:
styles.whatever.margin // error;
styles.product.color // okay
稍后,当您将它们传递给函数时,它会接受它或警告您:
someFunctionThatNeedsAStyleSheet(styles); // okay
someFunctionThatNeedsAStyleSheet(badStyles); // error!
// ----------------------------> ~~~~~~~~~
// Type '{ colour: string; }' has no properties in common
// with type 'Properties<string | 0>'
你做在这里进行类型检查。但当然,它不在您声明 styles
变量的同一位置。
如果你想在创建错误的 StyleSheet
时立即捕获它,你可以通过创建这样的辅助函数来使用上述类型检查函数的想法:
const asStyleSheet = <T extends StyleSheet>(t: T) => t;
函数asStyleSheet()
是一个通用的身份函数:它returns它的输入,与输入的类型相同。但是泛型是constrained到StyleSheet
,所以传错了就会报错。像这样:
const styles = asStyleSheet({ product: { color: 'gray' } }); // okay
const badStyles = asStyleSheet({ product: { colour: 'grey' } }) // error!
// ---------------------------------------> ~~~~~~~~~~~~~~
// 'colour' does not exist in type 'Properties<string | 0>'.
// Did you mean to write 'color' ?
通过使用 asStyleSheet()
,您正在检查 styles
的类型而不更改它; asStyleSheet()
的输出与输入的类型相同。所以编译器记住它的属性:
styles.whatever.margin // error;
styles.product.color // okay
看起来不错。
好的,希望对您有所帮助;祝你好运!