簡體   English   中英

具有可變原因的模板字符串文字:類型 s 的參數不可分配給類型參數

[英]template string literal with variable cause: Argument of type s not assignable to parameter of type

這是這個問題的一個連續問題: 有什么方法可以區分字符串和模板字符串文字

type Data = {
  arrayObject: {
    firstName: string;
    lastName: string;
  }[];
};

type ArrayElementType<A> = A extends readonly (infer T)[] ? T : never

type TupleOf<A extends number, R extends number[] = []> =
  R['length'] extends A ? R : TupleOf<A, [...R, R['length']]>;

type Integers = TupleOf<1>;

type Indexes = Integers[number];

type PathFinder<T, Key extends keyof T = keyof T> = Key extends string
    ? T[Key] extends (string | boolean | number | symbol)[]
      ? `${Key}.${Indexes}`
      : T[Key] extends object[]
        ? `${Key}.${Indexes}.${PathFinder<ArrayElementType<T[Key]>>}`
        : T[Key] extends Record<string, any>
          ? `${Key}.${PathFinder<T[Key]>}`
          : Key
    : never;

function register<Data>(name: PathFinder<Data>) {
  console.log(name)
}

const index = '0'

register(`arrayObject.${index}.lastName` as const); // works for TS 4.1
register(`arrayObject.${index}.lastName`); // works for TS 4.2

const i:number = '0'
register(`arrayObject.${index}.lastName` as const); fail
register(`arrayObject.${index}.lastName`); // fail

但是,當索引是動態的並且類型是number時,例如它可能導致for lop ,這會再次破壞類型。 有沒有辦法在模板字符串文字類型中包含numberstring類型?

操場

有一個小的StringNumber hack。

解決方案:

const index = '0';

const lit = `arrayObject.${index}.lastName`;
// const lit: string

const litAsConst = `arrayObject.${index}.lastName` as const;


namespace Orig {
  type Data = {
    arrayObject: {
      firstName: string;
      lastName: string;
    }[];
    firstName: string;
  };

  type ArrayElementType<A> = A extends readonly (infer T)[] ? T : never

  type TupleOf<A extends number, R extends number[] = []> =
    R['length'] extends A ? R : TupleOf<A, [...R, R['length']]>;

  type Integers = TupleOf<1>;

  type Indexes = Integers[number];

  type PathFinder<T, Key extends keyof T = keyof T> = Key extends string
    ? T[Key] extends (string | boolean | number | symbol)[]
    ? `${Key}.${Indexes}`
    : T[Key] extends object[]
    ? `${Key}.${Indexes}.${PathFinder<ArrayElementType<T[Key]>>}`
    : T[Key] extends Record<string, any>
    ? `${Key}.${PathFinder<T[Key]>}`
    : Key
    : never;

  function register<Data>(name: PathFinder<Data>) {
    console.log(name)
  }

  type StringNumber<T extends number> = `${T}` // <---- my solution is here

  const index: StringNumber<0> = '0'
  const result = register<Data>(`arrayObject.${index}.lastName` as const);
  register<Data>('firstName');
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM