【问题标题】:Can a string literal type and type "string" be mixed and used as key in a mapped type?字符串文字类型和“字符串”类型可以混合并用作映射类型中的键吗?
【发布时间】:2021-01-14 19:20:35
【问题描述】:

我想定义一个映射类型,其中键 'foo''bar' 的类型为 number,所有其他键的类型为 string

我的第一个直觉是用这样的条件类型来解决这个问题:

type FooOrBar =  'foo' | 'bar';

type MyMappedType = {
        [key in FooOrBar | string]: key extends FooOrBar ? number : string;
}

var x: MyMappedType = {
    foo:  1,   // Type 'number' is not assignable to type 'string'.(2322)
    bar:  2,   // Type 'number' is not assignable to type 'string'.(2322)
    baz: 'I am a string'   // ok!
}

Example 1

这里的问题是 typescript 将 typealias FooOrBar | string 缩小到在 key 中键入 string。所以实际上打字稿将这种类型评估为

type MyMappedType = {
        [key in string]: key extends FooOrBar ? number : string;
}

所以条件key extends FooOrBar 始终为假,类型定义对我的需要毫无用处。

我的第二个直觉是使用交叉类型:

type FooOrBar =  'foo' | 'bar';

type MyMappedType = {
        [key in FooOrBar]:number;
} & {
        [key in string]:  string;
};

var x: MyMappedType = { //       Type 'number' is not assignable to type 'string'.(2322)
    foo:  1,
    bar:  2,   
    baz: 'I am a string'  
}

Example 2

但这也不起作用。

有没有可能在 typescript 中定义这样的类型?

【问题讨论】:

    标签: typescript types


    【解决方案1】:

    您可以为每个索引案例创建属性,例如

    type numberLiterals = 'foo' | 'bar'
    
    type myMappedType = {
        numbers: { [key in numberLiterals]: number; };
        strings: { [key: string]: string }; 
    }
    
    var x: myMappedType = {
        numbers: {
            foo: 1,
            bar: 2,
            // zzz: 5 -> not assignable
        },
        strings: {
            fo: '',
            fooo: ''
            // baar: 1 -> not assignable
        }
    }
    

    Playground

    【讨论】:

    • 嗯,是的,这可行,但它更多的是一种解决方法而不是解决方案。我宁愿为我的代码结构定义类型,也不愿将我的代码结构调整为类型。
    • @Simon 我认为不可能对字符串执行此操作,因为[key: string] 已经允许任何字符串(包括您的联合类型中的字符串)。不过你可以使用数字。
    • @Simon 实际上,经过一番挖掘,您可以将交叉点更改为联合,它应该可以按预期工作。由于上述原因,我仍然不是它的粉丝。
    • Union 将允许初始分配,但您将无法访问“字符串索引”道具 (x['baz']) typescriptlang.org/play?#code/…
    • @AlekseyL。啊,你是对的,FooOrBar 属性在访问它们时也会变成string | number。猜猜我的第一个直觉是正确的
    猜你喜欢
    • 1970-01-01
    • 2023-02-07
    • 2020-06-07
    • 2020-01-17
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多