繁体   English   中英

如何摆脱警告“类型……不可分配给类型”打字稿

[英]How to get rid of warning 'Type … is not assignable to type' typescript

这可能是一个愚蠢的问题,但我想知道如何摆脱currentNum变量中的警告。 警告是 = ' Type 'string' 不可分配给类型 'StrType' '。 currentNum变量是存在于 StrType 类型中的字符串。 但它向我显示了警告

type StrType = 'one' | 'two' | 'three'

const initialNum = 'one1'

const currentNum: StrType = initialNum.slice(0, initialNum.length - 1)

确保您获得StrType类型的字符串的唯一实用的类型安全方法是将String.prototype.slice结果的类型从string缩小到您的类型。 您可以使用任何 类型缩小技术。 您也可以使用自定义保护断言函数

带类型保护:

type StrType = 'one' | 'two' | 'three'

const initialNum = 'one1'

function isStrType(str: string): str is StrType {
  return ['one', 'two', 'three'].includes(str)
}

const maybeStrType = initialNum.slice(0, initialNum.length - 1)

if (isStrType(maybeStrType)) {
  const currentNum: StrType = maybeStrType; // no error
}

游乐场链接


虽然如果你想在编译时确保它,你必须在类型级别“提升”你的slice函数和索引。 皮亚诺数是一个很好的例子,说明如何在类型级别上表示自然数的算术。

首先,我们必须定义我们的类型级数字:

type Zero = "zero" // base case

type Succ<N> = { n: N } // inductive step

这足以表示 0 和所有自然数;

type One = Succ<Zero>
type Two = Succ<One>
type Three = Succ<Two>
type Four = Succ<Three>
type Five = Succ<Four>
type Six = Succ<Five>
type Seven = Succ<Six>
type Eight = Succ<Seven>
type Nine = Succ<Eight>
type Ten = Succ<Nine>

type Decrement<N> = N extends Succ<infer R> ? R : Zero

type Num = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten

// helper function to convert Num to number
function fromNum(n: Num, acc: number = 0): number {
    return (n === "zero") ? acc : fromNum(n.n, acc + 1);
}

// --- some Num constants
const zero: Zero = "zero"
const one: One = { n: zero }
const two: Two = { n: { ...one } }
const three: Three = { n: { ...two } }
const four: Four = { n: { ...three } }
const five: Five = { n: { ...four } }

然后我们必须定义Slice类型。 我们得到字符串S ,起始索引From和结束索引To 我们还有累加器字符串R 一开始我们将它分配给空字符串''

在每一步中,我们将S拆分为First字符和字符串的Rest部分。

  • 如果FromZero但我们丢弃第一个字符,减少FromTo索引并使用减少的索引和Rest字符串调用Slice 蓄能器保持不变。
  • 如果From ZeroToZero ,我们减少ToFirst字符添加到累加器R的末尾,并使用字符串的Rest部分调用Slice ,减少To索引和连接累加器。
  • 如果From ZeroTo Zero我们已经到达切片过程的最后一步并返回累积的字符串R
type Slice<S extends string, From extends Num, To extends Num, R extends string = ''> = S extends `${infer First}${infer Rest}`
    ? From extends Zero
        ? To extends Zero
            ? R
            : Slice<Rest, Zero, Decrement<To>, `${R}${First}`>
        : Slice<Rest, Decrement<From>, Decrement<To>, R> 
    : R

游乐场链接

不过,我强烈建议不要在生产中使用它。

您可以使用类型断言说 slice 的结果将始终是StrType 类型

const currentNum = initialNum.slice(0, initialNum.length - 1) as StrType;

暂无
暂无

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

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