简体   繁体   English

递归地将TypeScript类型设置为非只读而不破坏元组

[英]Recursively setting a TypeScript type not read-only without clobbering tuples

export type DraftObject<T> = {-readonly [P in keyof T]: Draft<T[P]>}
export interface DraftArray<T> extends Array<Draft<T>> {}
export type Draft<T> = T extends any[]
    ? DraftArray<T[number]>
    : T extends ReadonlyArray<any>
        ? DraftArray<T[number]>
    : T extends object ? DraftObject<T> : T


type tup = [number, number, number, number]

const T: Draft<tup> = [1, 2, 3, 4]
const U: tup = [1, 2, 3, 4]

const TT: tup = T
const UU: Draft<tup> = U

The type DraftObject should return any type with all its properties marked not read-only. DraftObject类型应返回其所有属性都标记为非只读的任何类型。 This works in all cases, except tuple types, where they're incorrectly turned into arrays. 这在所有情况下都有效,除了元组类型(元组类型错误地将它们错误地变成数组)。 How can I special case tuples, and Readonly<> them instead of making them DraftArray s? 我该如何特殊化元组和Readonly<>而不是使它们成为DraftArray呢?

If, for some reason, you need to detect the difference between tuples and arrays, you can use the fact that tuple types have a known "0" key (the string value, not the number 0 ) but arrays do not: 如果由于某种原因需要检测元组和数组之间的差异,则可以使用以下事实:元组类型具有已知的"0"键(字符串值,而不是数字0 ),而数组则没有:

type IfTuple<T extends any[], Y=true, N=false> = "0" extends keyof T ? Y : N

type TestTuple = IfTuple<[string, number], "tuple", "array">; // "tuple"
type TestArray = IfTuple<string[], "tuple", "array">; // "array"

This should be enough to build a conditional type that does something different for tuples from what it does for general arrays. 这足以建立一个条件类型,该条件类型对元组所做的操作与对常规数组所做的操作有所不同。

Hope that helps. 希望能有所帮助。 Good luck! 祝好运!

As jcalz said, there are no readonly tuples as of TypeScript 3.1. 正如jcalz所说,TypeScript 3.1尚无只读元组。 If you want to make everything mutable, you can just use: 如果您想使一切变得可变,则可以使用:

export type Draft<T> = {-readonly [P in keyof T]: Draft<T[P]>};

taking advantage of the mapped tuples and arrays added in TypeScript 3.1 and the previously existing special case for homomorphic mapped types applied to primitives ( Draft<T> evaluates to T when T is primitive). 利用TypeScript 3.1中添加的映射元组和数组以及应用于原语的同态映射类型的先前存在的特殊情况(当T为原语时, Draft<T>评估为T )。

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

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