简体   繁体   English

在 TypeScript 中定义一个空对象类型

[英]Define an empty object type in TypeScript

I'm looking for ways to define an empty object type that can't hold any values.我正在寻找定义不能保存任何值的空对象类型的方法。

type EmptyObject = {}

const MyObject: EmptyObject = {
  thisShouldNotWork: {},
};

Objects with the type are free to add any properties.具有该类型的对象可以自由添加任何属性。 How can I force MyObject to always be an empty object instead?如何强制MyObject始终为空对象?

My actual use case is using the EmptyObject type inside an interface.我的实际用例是在接口内使用 EmptyObject 类型。

interface SchemaWithEmptyObject {
  emptyObj: EmptyObject; 
}
type EmptyObject = {
    [K in any] : never
}

const one: EmptyObject = {}; // yes ok
const two: EmptyObject = {a: 1}; // error

What we are saying here is that all eventual properties of our EmptyObject can be only never , and as never has no representing value, creating such property is not possible, therefor the object will remain empty, as this is the only way we can create it without compilation error.我们在这里要说的是EmptyObject的所有最终属性都只能是never ,并且由于never没有代表值,因此创建这样的属性是不可能的,因此对象将保持为空,因为这是我们创建它的唯一方法没有编译错误。

type EmptyObject = Record<any, never>

这相当于Maciej Sikora 的答案,但使用了Record 实用程序类型

根据 VSC type emtyObj = Record<string, never>

There are several options for defining an empty object type, and it completely depends on the side-effects you want regarding your linter and typescript errors when accessing or setting properties.定义空对象类型有几个选项,它完全取决于您在访问或设置属性时想要的关于 linter 和 typescript 错误的副作用。 These are the options I tried:这些是我尝试过的选项:

// Option A:
let objA: Record<any, never> = {}; // Typescript-ESLint error: Unexpected any. Specify a different type.
objA = { prop: 'value' }; // Typescript error: Type 'string' is not assignable to type 'never'.
console.log(objA.prop);
console.log(objA.nonExistingProp); // No error!!!

// Option B:
let objB: Record<string, never> = {};
objB = { prop: 'value' }; // Typescript error: Type 'string' is not assignable to type 'never'.
console.log(objB.prop);
console.log(objB.nonExistingProp); // No error!!!

// Option C:
let objC: Record<never, never> = {};
objC = { prop: 'value' };
console.log(objC.prop); // Typescript error: Property 'prop' does not exist on type 'Record<never, never>'
console.log(objC.nonExistingProp); // Typescript error: Property 'nonExistingProp' does not exist on type 'Record<never, never>'.

TLDR: Record<string, never> raises errors when setting properties to the empty object. TLDR: Record<string, never>在将属性设置为空对象时引发错误。 Record<never, never> raises errors when accessing properties of the empty object. Record<never, never>在访问空对象的属性时引发错误。 I have yet to find a solution that raises errors in both cases.我还没有找到在这两种情况下都会引发错误的解决方案。

Personally I went with option C for my current use-case, because I wanted an error to happen if I try to access a property of an empty object, but you may not want that!就我个人而言,我为当前的用例选择了选项 C,因为我希望在尝试访问空对象的属性时发生错误,但您可能不希望这样!

How about something like this with a private symbol?像这样带有私有符号的东西怎么样?

// EmptyType.ts
const EMPTY_SYMBOL = Symbol();
export type EmptyType = {[EMPTY_SYMBOL]?: never};

It works correctly against an intersection union type.它适用于交叉联合类型。

import {EmptyType} from "./EmptyType";
type Union = EmptyType | { id: string };
const a: Union = {};
const b: string = a.id; // <-- error

TypeScript Playground 打字稿游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM