microsoft / microsoft/TypeScript

Omitted arguments are not candidates for possibly-undefined type parameters

Đang mở
#61,069 0 bình luận 0 reaction 1 người được giao Xem trên GitHub

@gabritto đang làm issue này rồi.

Từ ngày 31/1/2025.

Domain: check: Type Inference Possible Improvement
Ngôn ngữ chính
Go
Star
111k
Fork
14.3k
Merge trung bình
2 ngày 4 giờ
Pull request đã merge (30 ngày)
132

Mô tả

# Background

[Playground Link](https://www.typescriptlang.org/play/?isolatedDeclarations=false&ts=5.8.0-dev.20250128#code/C4TwDgpgBAigrgSwMYGsAKyUCULDgJwDsAeAWTgBtgEwLoIAPYCQgEwGcoAjAex7oCGhKAB8ocNhABmCQhFYA+KAF4AUFA1RyVGnSiNmbTsHxxoAfijsTsgOYBtALpQAXOs3bqtekxYcoUgIU7NBiEqzSsvJQltb4dq7uGnIAbhD4ANyqqgD0AFR56nlQAAJgAvgCALZQYPg8VWDAUAAqABbQzExQwDxWbTwA7j19AuIh+AB0RaXllTUIzFWcAOodwB34UGNwE1BIQlYQdEjNVZReejxNCDyE7AA0UDxbAFa7zWPsdlc3d9NQYplCrVfZCADKxwgp08umgAFEBEg2s8pD0Os8-vdavgICFCMxWCN0dBdukAQUcqopBJTrdhOwBoN4JgMKgyBc4fpfEZuHxBMIwpIZHJFAAKJI4hpNFxWGyEWwPSWLCDLWW4gSsO4UEBy+IKpxKzRgwiQk7AWHecyyy10JUASllLNQbOwuAIJFtECUAG9JXRmlw4MBetjlFAVctJlUBGAxWLI09ZBEGPaVEoxX7jcaQub5LLk4wVMpwwAGI3ZjRdYAFpYVjQAX3t9qykpyOWeG3S+x4ESgth4eJ7fc2EEm4+yxoQaLFB1NUJhnO8aazlaguLwRG4wdD7Ela6gkxkVHSYqDIbu6e3F8Ik1z0MJ9v3a+jsbPO8vyiU59Dk2rLclBtJQ3D1r13I9k3fG8rx-f571OeR7QAQj-AwsiA3IOwAAxMMwsP7BA0k4MYsLiOwnHwgBaKBBheFBOEAUHJVADfprjAOwABkEGsWUyINZxw0ZIZnXQTAJWNAAiNZkBRKRTEWTgtSgEAeDgGihGaXpagIZEBBCcwJPrKB7Ak2NvHYQyoAkl4hFsPFLIkrghGciyngk1gCAQIQJMcIzcIgB1WyQO52H4McKB4WwxSwgBBCh4lsNpgCeAcElUzS+iDXVQqqaAABIfSEsB2IVLjrEmV4eFkMUHPtBssIAzCoCw8JIlFfDbEIocSL42wqJoujGOY3AoFYWQ5HwABGXj5VsFRWOZRAXTEyUpLaARgAAck4KQXlG8bu1DBBEuAAyjJM9hdjaBAHPKawBAc4AkR4VyrLgRKoAASU2mpej6NoJFsfBdS0jZZBQJ5BnW5g0i2FS1MGDSfKMwJggC1RGvbZrWpFeQOq64jmt6-raPweioCYlixsICaACYZv1ObBKZETXXEzQ1o27aAj26mJpGQhjqSs7JQuq6brcu6nse57Xok96UW+36+CgAGFWB4kwcICGaOhiBYeU1T1IJZHJRxqJWEC7IsYAeSqRZCW2fBbDgXKCQIojtiJ2bRD1cjHH6wAZcmG5o+fSABmBmEmZ4SltE1B2Y0Tmtp23mDq2I6TpF40xcZCWrKlh63Ke4K5YVr6fpGf7AY10Hru1yG9YN+HjeAU2WyAA)

Consider the following code that is trying to leverage #56941.

```ts
type QuickPickReturn =
Multiple extends true ? string[] :
Multiple extends false | undefined ? string :
never;

/**
* @param prompt The text to show to a user.
* @param items Whether a user can select multiple options, or just a single option.
* @param canSelectMultiple Each of the options presented to the user.
**/
function showQuickPick(
prompt: string,
items: readonly string[],
canSelectMultiple?: Multiple,
): QuickPickReturn {
let buttons = items.map((item, index) => ({
selected: index === 0,
text: item,
}));

// other code goes code here...

if (canSelectMultiple) {
return buttons
.filter(button => button.selected)
.map(button => button.text);
}
return buttons.find(button => button.selected)!.text;
}
```

This code has an optional parameter `canSelectMultiple`. Because it is optional, the `Multiple` type parameters cannot simply be constrained to `boolean` - they must factor in `undefined` for various narrowing and assignability checks to work out.

Most calls work as expected.

```ts
// `true` gives a `string[]` - works ✅
let shoppingList: string[] = showQuickPick(
"Which fruits do you want to purchase?",
["apples", "oranges", "bananas", "durian"],
true,
);

// `false` - works ✅
let dinner: string = showQuickPick(
"What's for dinner tonight?",
["sushi", "pasta", "tacos", "ugh I'm too hungry to think, whatever you want"],
false,
);
```

`undefined` explicitly also works

```ts
// `undefined` gives a `string` - works ✅
let dinner2: string = showQuickPick(
"What's for dinner tonight?",
["sushi", "pasta", "tacos", "ugh I'm too hungry to think, whatever you want"],
undefined,
);
```

However, if we omit the argument, we assume that there are no candidates for inference available and fall back to the constraint `boolean | undefined`. This changes our output type to `string | string[]`, which is an error in the following code:

```ts
// Omitted argument gives a `string | string[]` - ❌
let dinner3: string = showQuickPick(
"What's for dinner tonight?",
["sushi", "pasta", "tacos", "ugh I'm too hungry to think, whatever you want"],
);
```

# Proposal

When TypeScript infers type arguments to type parameters based on actual call arguments, we walk through parameters with missing corresponding arguments and infer from the type `undefined` to each parameter's type.

Some things to consider if we discuss this:

* How would this function with missing *properties*? Do we need to do something similar there?
* Is it always desirable to do this inference? Do we need a different inference priority?
* This behavior is correct for purely-optional parameters, but is it correct for parameters with default arguments? (I realized this hairball of a problem after posting this issue)

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.