Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: typeguard 타입추론 개선 #284

Merged
merged 1 commit into from
Oct 17, 2024
Merged

Conversation

rojiwon123
Copy link
Contributor

Fixes #
기존 타입가드 함수의 타입 추론 결과의 정확도를 향상시켰습니다.
최신 TS 버전은 타입가드의 결과를 input 타입과 교집합으로 계삽합니다. 이를 참고하여 타입 연산식을 수정했습니다.

아쉽게도 여전히 input이 any인 경우는 잘못된 결과가 추론됩니다.

before

isString(input: any); // input is any;
isString(input: unknown); // input is never;
isString(input: number | "1" | "2"); // input is "1" | "2";

after

isString(input: any); // input is any;
isString(input: unknown); // input is string;
isString(input: number | "1" | "2"); // input is "1" | "2";
isString(input: number); // input is never;

@rojiwon123
Copy link
Contributor Author

is 함수의 인자인 input을 unknown으로 정의하면 any를 포함한 타입추론이 꽤 잘 이루어집니다. 하지만 unless 같은 다른 유틸 함수들과 함께 사용할 경우, 오히려 기존 인자의 타입을 상실하게 되기에 아직도 개선의 여지가 남아있습니다.

@ppeeou
Copy link
Member

ppeeou commented Oct 14, 2024

@rojiwon123 Thank you for your interest and contribution.

It seems that the PR example enhances the type inference for isString, but I don't see that in the code. Could you also include the details about how the type inference for isString has been improved?

@rojiwon123
Copy link
Contributor Author

rojiwon123 commented Oct 14, 2024

@rojiwon123 Thank you for your interest and contribution.

It seems that the PR example enhances the type inference for isString, but I don't see that in the code. Could you also include the details about how the type inference for isString has been improved?

@ppeeou 기존 Include<T,E> 타입의 연산은 기본적으로 T ) U 인 경우, never를 반환했습니다.
그래서 isString 함수의 인자로 unknown 타입의 값을 입력하면 Include<unknown, string>의 결과로 never가 추론됩니다.

타입 가드 연산은 Include 연산이 아니라 Intersect 연산(교집합)이 더 정학한 것 같습니다.

T & E 타입 연산에서 unknown & string은 string으로 나타나며 ("a" | number | "b") & string 은 "a" | "b" 로 추론됩니다.

해당 PR은 이와같이 타입 가드 함수들의 시그니처를 수정하고 그에 맞춰 일부 테스트 코드나 컴파일 에러가 발생하는 코드들을 수정했습다.

실제 예로 기존에 dropRight 함수에서 isArray(iterable) || isString(iterable) 연산의 결과는 never 타입이었습니다. 따라서 arr은 never | T[] 로 연산되어 T[] 가 결과로 나타난 것입니다.

아쉽게도 Iterable & T[] 연산은 T[]로 추론되지 않습니다. 그래서 오히려 arr[i]에 T를 assertion 해야 했습니다.

import isArray from "../isArray";
import isString from "../isString";
import toArray from "../toArray";
import type ReturnIterableIteratorType from "../types/ReturnIterableIteratorType";
import concurrent, { isConcurrent } from "./concurrent";
function* sync<T>(length: number, iterable: Iterable<T>) {
  const arr =
    isArray(iterable) || isString(iterable) ? iterable : toArray(iterable);
  for (let i = 0; i < arr.length - length; i++) {
    yield arr[i] as T;
  }
}

Comment on lines +1 to +5
import type Falsy from "./Falsy";

type FalsyTypesOf<T> = T extends Falsy ? T : never;

export default FalsyTypesOf;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this code intended to be used?

Copy link
Member

@ppeeou ppeeou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for your contribution👍

@ppeeou ppeeou merged commit 850820a into marpple:main Oct 17, 2024
1 check passed
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