0

我想根据 TypeScript 中另一个对象的键创建一个类型。

我已经设法通过类型推断来做到这一点。但是,如果我使用显式类型Record<string, something>,则keyof给我string而不是我使用的实际键的联合。

TypeScript 游乐场 GIF

这是示例代码:

type FileType = "image" | "video" | "document";

type FileTypeList = Record<string, FileType>

const inferedFileList = {
    a: "image",
    b: "video",
    c: "document"
}

//type files = "a" | "b" | "c"
type files = keyof typeof inferedFileList;

const explicitelyTypedList : FileTypeList = {
    a: "image",
    b: "video",
    c: "document"
}

//type typedFiles = string
type typedFiles = keyof typeof explicitelyTypedList;

相关的 TypeScript Playground

有什么方法可以在表单中使用显式类型Record<string, something>并仍然获得联合类型keyof吗?我想可以使用行为类似typeof但使用对象的形状而不是其声明的类型的关键字,但是 TypeScript 是否实现了这样的事情?

4

2 回答 2

0

类型推断在 TypeScript 中非常强大,不自己注释类型并没有错。

当您显式键入对象时,实际上键入的精度会降低:

const aString = "a" as const; // typeof aString is 'a'
const justString: string = aString; // typeof justString is 'string'

也许您在此过程的后期需要这种类型,因此您可以执行以下操作:

type FileTypeRecord = Record<keyof typeof inferedFileList, FileType>

所以只使用现有的键(a,b,c)获取整个记录类型

如果您想保护该对象具有有效值但也具有静态已知键,您可以尝试这种方法:

type FileType = "image" | "video" | "document";

function getTypedFileObject<T extends { [k: string]: FileType }>(blueprint: T) : Record<keyof T, FileType> {
  return blueprint;
}

const obj = getTypedFileObject({
    a: "image",
    b: "video",
    c: "document",
    // d: "test" will not compile
})
于 2020-12-11T22:36:01.287 回答
0

也许它会帮助你:

type FileType = "image" | "video" | "document";

const inferedFileList = {
    a: "image",
    b: "video",
    c: "document"
}

type FileTypeList = Record<keyof typeof inferedFileList, FileType>

const explicitelyTypedList : FileTypeList = {
    a: "image",
    b: "video",
    c: "document"
}

//type typedFiles = string
type typedFiles = keyof typeof explicitelyTypedList; // a | b | c
于 2020-12-12T14:04:54.230 回答