![](/img/trans.png)
[英]Argument of type 'string' is not assignable to parameter of type 'string[]'
[英]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
,這會再次破壞類型。 有沒有辦法在模板字符串文字類型中包含number
或string
類型?
有一個小的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.