我试图定义一个与任何对象/字典匹配但不匹配数组的类型。
我的第一次尝试没有成功,因为从技术上讲,数组是底层的对象:
const a:{[k:string]: any} = []; // works fine
Run Code Online (Sandbox Code Playgroud)
我还知道可以创建一个通用的“检查器”,如下所示:
type NoArray<T> = T extends any[] ? never : T;
Run Code Online (Sandbox Code Playgroud)
但这不是我要找的。我想要一个像这样工作的非泛型类型:
const a: NoArrayType = {}; // works fine
const a: NoArrayType = []; // TypeError
Run Code Online (Sandbox Code Playgroud)
/**\n * Constrains a type to something other than an array.\n */\nexport type NotArray = (object | string | bigint | number | boolean) & { length?: never; };\nRun Code Online (Sandbox Code Playgroud)\n这超出了原始海报所寻求的范围,但可以轻松调整:
\n/**\n * Constrains a type to an object other than an array.\n */\nexport type NonArrayObject = object & { length?: never; };\nRun Code Online (Sandbox Code Playgroud)\n不使用索引签名的优点是,如果访问不存在的属性,则会出现错误:
\nfunction test(hello: NonArrayObject) {\n return hello.world; // error\n}\nRun Code Online (Sandbox Code Playgroud)\nusing 的缺点\xe2\x80\xa6\xc2\xa0& { length?: never; }是您可以访问 的length属性NotArray,不能将其用于恰好具有length属性的对象,并且不能将其用于函数,因为它们具有length属性。
如果有人想知道,我用来NotArray定义可选的返回值,在大多数情况下,只有第一个返回值是令人感兴趣的:
export type OptionalReturnValues2<T1 extends NotArray, T2> = T1 | [T1 | undefined, T2];\n\nexport function normalizeReturnValues2<T1 extends NotArray, T2>(optionalReturnValues: OptionalReturnValues2<T1, T2>): [T1 | undefined, T2 | undefined] {\n if (Array.isArray(optionalReturnValues)) {\n return optionalReturnValues;\n } else {\n return [optionalReturnValues, undefined];\n }\n}\n\nexport type OptionalReturnValues3<T1 extends NotArray, T2, T3> = T1 | [T1 | undefined, T2] | [T1 | undefined, T2 | undefined, T3];\n\nexport function normalizeReturnValues3<T1 extends NotArray, T2, T3>(optionalReturnValues: OptionalReturnValues3<T1, T2, T3>): [T1 | undefined, T2 | undefined, T3 | undefined] {\n if (Array.isArray(optionalReturnValues)) {\n return [optionalReturnValues[0], optionalReturnValues[1], optionalReturnValues[2]];\n } else {\n return [optionalReturnValues, undefined, undefined];\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
类型问题出any在类型声明中。any在大多数打字稿应用程序中通常是您想要避免的事情。
数组只是一个可以用数字键索引的对象,并且有一些额外的方法。事实上,您几乎可以为该类型分配任何非原始值。
const a: {[k:string]: any} = [1,2,3]; // works
const b: {[k:string]: any} = {a: 123}; // works
const c: {[k:string]: any} = () => { console.log(123) }; // works
const d: {[k:string]: any} = () => new AnyClass(); // works
Run Code Online (Sandbox Code Playgroud)
这与您可以执行以下操作的原因相同,因为这any是打字稿始终允许您将值转换为的一种情况。
const a: any = true
const b: any = {}
const c: any = new AnyClass()
Run Code Online (Sandbox Code Playgroud)
所以你有几个选择。
any. 如果您知道这些属性的可能值,请声明它们。interface MyObjectType { [k: string]: number | string }
const a: MyObjectType = [] // fails
const b: MyObjectType = {} // works
Run Code Online (Sandbox Code Playgroud)
或者也许这就是JSON?如果是这样,any则不是正确的类型,因为您知道它不能包含某些内容(例如类实例或函数)。
interface Json {
[key: string]: string | number | boolean | Json | Json[]
}
const a: Json = [] // type error
const b: Json = {} // works
Run Code Online (Sandbox Code Playgroud)
unknowntype 而不是any,这要求您在使用值之前在运行时检查类型。interface MyObjectType { [k: string]: unknown }
const a: MyObjectType = [] // type error
const b: MyObjectType = { prop: 123 } // works
// b.prop type here is: unknown
b.prop.toUpperCase() // type error
if (typeof b.prop === 'string') {
// a.prop type here is: string
console.log(b.prop.toUpperCase()) // works
}
Run Code Online (Sandbox Code Playgroud)
小智 5
type MapOnly = Record<任意键,未知>
| 归档时间: |
|
| 查看次数: |
7555 次 |
| 最近记录: |