TypeScript 如何强制转换强类型 ReadonlyMap(以排除 Map.get(key) 返回类型中的未定义)?

问题描述 投票:0回答:1

尝试使用Map来实现字典

但是,尽管输入所有可能的键并使用 ReadonlyMap Map.get(key) 返回 valueType |欠定义

type dictKeys = 'key1' | 'key2' | 'key3'

const dictObj:ReadonlyMap<DictKeys, string> = new Map<DictKeys, string>{
    key1: 'value1',
    key2: 'value2',
    key3: 'value3',
} satisfies Record<dictKeys, string>

function testDictObj(key: dictKeys) {
    const res = dictObj[key]
    return res
}

const dictMap:ReadonlyMap<DictKeys, string> = new Map([
    ['key1', 'value1'],
    ['key2', 'value2'],
    ['key3', 'value3'],
])

function testDictMap(key: dictKeys) {
    const res = dictMap.get(key)
    return res
}

恕我直言,TS 应该知道缩小范围所需的所有类型,以及如果映射中存在无效键的类型或缺少道具键定义 - 它会发出警告,因此

const res = dictMap.get(key)
应该只给出“字符串”类型

如果使用对象 - 一切都很好,但对于字典来说,使用映射更语义 是的,我可以使用断言“!”因为我对结果很确定,但它似乎不太整洁(

也许已经有walkaroung或自定义实用程序类型了?

typescript
1个回答
1
投票

虽然 TypeScript 可以对

object
类型进行类型推断,但它必须遵循 Map 类已定义的类型定义。
Map
ReadonlyMap
都定义了
get
方法,如下所示:

get(key: K): V | undefined;

所以 TypeScript 无法自动知道该值不能是

undefined

您可以像这样扩展

Map
类:

class StrictMap<K, V> extends Map<K, V> {
    public override get(key: K): V {
        const result = super.get(key);
        if (result === undefined) {
            throw Error("Key not found");
        }
        return result;
    }
}

通过使用此实现,get 方法永远不会返回

undefined
,而是抛出异常。

如果您需要将其转换为只读,您也可以扩展此接口:

interface ReadonlyStrictMap<K, V> extends ReadonlyMap<K, V> {
    get(key: K): V;
}

现在您的示例可以运行并且

get
返回
string
:

const dictMap = new StrictMap([
    ['key1', 'value1'],
    ['key2', 'value2'],
    ['key3', 'value3'],
]) satisfies ReadonlyStrictMap<dictKeys, string>;

function testDictMap(key: dictKeys) {
    const res = dictMap.get(key)
    return res // <-- Type: string
}

(编辑:示例中的

satisfies
并不是真正需要的,只需使其接近您自己的示例即可。)

© www.soinside.com 2019 - 2024. All rights reserved.