因为当有类型定义时 const 被忽略

Ben*_*arp 6 typescript typescript-typings

我想将对象限制为某种类型,但也想将其转换为“const”,以便可以按字面意思键入某些属性。但是,当我将“as const”与下面的代码中的类型定义一起使用时,推断的类型不是文字——“as const”被忽略。

interface IFilterBase {
   type: string
   ...
}

const COST_FILTER: IFilterBase = {
   type: "cost",
   ...
} as const
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,“as const”被忽略了。COST_FILTER.type被推断为string,而不是"cost"

有没有办法限制COST_FILTER为实现IFilterBase类型,但它的属性被推断为“作为常量”?

Tit*_*mir 6

如果您明确指定类型 typescript 将只检查与接口的兼容性。评论中概述了一项提案,以支持该语言。

在此之前,我们可以使用函数、元组和文字的推理规则:

  • 如果将字面量类型分配在一个被类型化为泛型类型参数的位置,则该字面量类型将被推断(或更好地说是保留)
  • 如果一个数组被分配到一个被类型化为约束为 的泛型类型参数的位置,则将推断出一个元组[unknown] | unknown[]

有了这些规则,我们就可以创建一个递归映射类型,将原始类型的属性映射到包含此类泛型类型参数的新类型。我们不会为每个属性分离类型参数,一个参数用于文字,一个用于元组。这足以向编译器提示我们想要什么。


type WithLiterals<T, L, LTuple> =  
    T extends string| number | boolean | null | undefined ? T & L :
    {
        [P in keyof T]: 
            WithLiterals<T[P], L, LTuple> & (T[P] extends Array<any> ? LTuple: unknown)
    }

type DeepReadonly<T> = {
    readonly [P in keyof T]: DeepReadonly<T[P]>
}

function asConst<TInterface>()
{
    return function<
        LTuple extends [unknown] | unknown[],
        L extends string | boolean | number, T extends WithLiterals<TInterface, L, LTuple>>(o: T): DeepReadonly<T> {
        return o as any
    }
}

type IFilterBase = {
    type: "cost" | "other",
    displayName: string | undefined,
    nr: number,
    nrUnion: 1 | 2,
    subObj : {
        a: string;
    }
    arr: string[]
    larr: ("A" | "B")[]
    mixedarr: (number | string)[],
    oArray: Array<{
        a: string
    }>
}

export const COST_FILTER = asConst<IFilterBase>()({
   type: "other",
   nr: 1,
   nrUnion: 1,
   displayName: "Cost",
   subObj: {
       a: "A"
   },
   arr: ["A", "B"],
   larr: ["A"],
   mixedarr: [1, ""],
   oArray: [
       { a: ""}
   ]
})

Run Code Online (Sandbox Code Playgroud)

键入为:

export const COST_FILTER : DeepReadonly<{
    type: "other";
    nr: 1;
    nrUnion: 1;
    displayName: "Cost";
    subObj: {
        a: "A";
    };
    arr: ["A", "B"];
    larr: ["A"];
    mixedarr: [1, ""];
    oArray: [{
        a: "";
    }];
}>
Run Code Online (Sandbox Code Playgroud)

关联