Reputation: 13933
While trying to implement Pick
, I was not sure why the type WrongPick
gives bad result with an |
.
interface Todo {
title: string
description: string
completed: boolean
}
type WrongPick<T, K> = K extends keyof T ? {[P in K]: T[P]} : never
type wrong_result = WrongPick<Todo, 'title' | 'completed'>
// expected: { title: string ; completed: boolean }
// actual: { title: string } | { completed: boolean }
type CorrectPick<T, K extends keyof T> = {[P in K]: T[P]}
type correct_result = CorrectPick<Todo, 'title' | 'completed'>
// expected: { title: string ; completed: boolean }
// actual: { title: string ; completed: boolean }
Upvotes: 0
Views: 43
Reputation: 26322
Because of distributive conditional types, WrongPick<Todo, "title" | "completed">
actually expands to
("title" extends keyof T ? { [P in "title"]: Todo[P] } : never) | ("completed" extends keyof T ? { [P in "completed"]: Todo[P] } : never)
which simplifies to
{ title: string } | { completed: boolean }
As described in the above link to the documentation, you can "turn it off" by wrapping both sides in tuples:
type WrongPick<T, K> = [K] extends [keyof T] ? { [P in K]: T[P] } : never
Upvotes: 3