Skip to content

Improve v-for type#546

Merged
johnsoncodehk merged 4 commits intovuejs:masterfrom
sapphi-red:improve-v-for-type
Oct 3, 2021
Merged

Improve v-for type#546
johnsoncodehk merged 4 commits intovuejs:masterfrom
sapphi-red:improve-v-for-type

Conversation

@sapphi-red
Copy link
Copy Markdown
Contributor

@sapphi-red sapphi-red commented Oct 2, 2021

Improved some types and added some tests.


Now v-for is transformed into the code below.

// when noUncheckedIndexedAccess: true
declare const record: Record<string, string>

declare function __VLS_getVforSourceType<T>(source: T): T extends number ? number[] : T;
declare function __VLS_getVforKeyType<T>(source: T): typeof Symbol.iterator extends keyof T ? number : keyof T;
declare function __VLS_getVforIndexType<T>(source: T): typeof Symbol.iterator extends keyof T ? undefined : number;
declare function __VLS_pickForItem<S, T2>(source: S, forInItem: T2): S extends { [Symbol.iterator](): IterableIterator<infer T1> } ? T1 : T2;

const __VLS_11 = __VLS_getVforSourceType(record) // Record<string, string>
for (const __VLS_12 in __VLS_11) {
    const val = __VLS_pickForItem(__VLS_11, __VLS_11[__VLS_getVforKeyType(__VLS_11)]) // string | undefined
    const key = __VLS_getVforKeyType(__VLS_11) // string
}

But val should not have undefined since it is not a index access.

So I changed the transformed result to be like below.

declare function __VLS_getVforKeyTypeNew<T>(source: T): typeof Symbol.iterator extends keyof T ? number : T extends T ? keyof T : never;
declare function __VLS_pickForItemNew<T>(source: T): T extends { [Symbol.iterator](): IterableIterator<infer T1> } ? T1 : T[keyof T];

const __VLS_21 = __VLS_getVforSourceType(record) // Record<string, string>
for (const __VLS_22 in __VLS_21) {
    const val = __VLS_pickForItemNew(__VLS_21) // string
    const key = __VLS_getVforKeyTypeNew(__VLS_21) // string
}

(__VLS_getVforKeyTypeNew does not effect this but I will explain the benefits below.)


While changing this, it affected some other patterns.
These are some examples.

declare const record: Record<string, string> // which I explained above
__VLS_pickForItem(record, record[__VLS_getVforKeyType(record)]) // string | undefined
__VLS_pickForItemNew(record) // string

declare const arr: ['a', 'b'] // no change
__VLS_pickForItem(arr, arr[__VLS_getVforKeyType(arr)]) // 'a' | 'b'
__VLS_pickForItemNew(arr) // 'a' | 'b'

declare const map: Map<string, number> // removed a error
__VLS_pickForItem(map, map[__VLS_getVforKeyType(map)]) // [string, number] with type error
__VLS_pickForItemNew(map) // [string, number]

declare const obj: { a: string, b: number } // no change
__VLS_pickForItem(obj, obj[__VLS_getVforKeyType(obj)]) // string | number
__VLS_pickForItemNew(obj) // string | number

declare const objUnion: { a: string } | { a: string, b: number } // better type, key should behave same so I changed __VLS_getVforKeyType
__VLS_pickForItem(objUnion, objUnion[__VLS_getVforKeyType(objUnion)]) // string
__VLS_pickForItemNew(objUnion) // string | number
__VLS_getVforKeyType(objUnion) // 'a'
__VLS_getVforKeyTypeNew(objUnion) // 'a' | 'b'
// https://stackoverflow.com/a/49402091

TS Playground

@johnsoncodehk
Copy link
Copy Markdown
Member

LGTM, thank you!

@johnsoncodehk johnsoncodehk merged commit 9ff5fbb into vuejs:master Oct 3, 2021
@sapphi-red sapphi-red deleted the improve-v-for-type branch October 3, 2021 04:04
@johnsoncodehk
Copy link
Copy Markdown
Member

FYI, objUnion is not longer supported since 529415e, because which broke generic type.

@sapphi-red
Copy link
Copy Markdown
Contributor Author

Thank you for telling me 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants