TypeScript: 유형 기반 이진 가산기
17909 단어 webdevfunnytypescript
안녕하세요!
TypeScript는 이제 Variadic Tuple Types 을 지원합니다. 배열과 같은 유형을 다른 유형으로 변환하는 유형을 생성하기 위해 확산 연산자 및 일반 매개변수를 사용할 수 있음을 의미합니다. 예를 들어 배열에 요소를 추가하는 유형을 만들어 보겠습니다.
type Append<T extends unknown[], R> = [R, ...T];
let a1: Append<[1, 2, 3], 0>;
// ^ = let a1: [0, 1, 2, 3]
let a2: Append<[], "some">;
// ^ = let a2: ["some"]
let a3: Append<[1, "q", false], {a: number}>;
// ^ = let a3: [{a: number}, 1, "q", false]
playground
좋습니다. 하지만 배열의 첫 번째 요소를 제거하는 유형을 만들고 싶다면 어떻게 해야 할까요? 이 유형은 빈 배열
[]
이 확장unknown[]
하고 원래 배열에 요소가 있는지 확인해야 하기 때문에 그렇게 간단하지 않습니다. conditional type 및 type inference을 사용하여 이를 수행할 수 있습니다.type Slice<T extends unknown[]> = T extends [infer _, ...infer Tail]
? Tail
: [];
let b1: Slice<[1, 2, 3]>;
// ^ = let b1: [2, 3]
let b2: Slice<[1]>;
// ^ = let b2: [];
let b3: Slice<[]>;
// ^ = let b3: [];
playground
작업을 복잡하게 합시다. 배열을 뒤집을 유형을 만드는 방법은 무엇입니까? 일반적인 상황에서는 루프 또는 재귀를 사용하여 배열을 반복합니다. Typescript 유형에서는 recursive type alias 을 사용할 수 있습니다.
type Reverse<T extends unknown[]> =
T extends [infer Item, ...infer Tail]
? [...Reverse<Tail>, Item]
: [];
let c1: Reverse<[1, 2, 3]>;
// ^ = let c1: [3, 2, 1]
let c2: Reverse<[1]>;
// ^ = let c2: [1]
let c3: Reverse<[]>;
// ^ = let c3: []
playground
이 접근법에는 불쾌한 순간이 하나 있습니다. typescript는 추론 유형을 정의하기 위해 제네릭의 제약 조건을 사용하지 않습니다.
type Some<T extends number> = T
가 있는 경우 정의된 유형을 T 매개변수로 유추할 수 없습니다.type Some<A extends number> = A;
type Some2<A extends number[]> = A extends Array<infer B>
? Some<B>
// ^ Error: Type 'B' does not satisfy the constraint 'number'
: number;
그러나
Some
유형을 type Some<T> = T extends number ? T : number
로 변경하면 유추된 유형을 사용할 수 있습니다. Some
유형의 이 두 버전은 동일하지 않지만 때때로 이 접근 방식을 사용할 수 있습니다.유형 기반 이진 가산기
자, 이제 우리는 이진 가산기를 만드는 모든 것을 알고 있습니다. 이진 가산기가 무엇인지 모르는 경우 learn it yourself 할 수 있습니다. 먼저 몇 가지 논리 연산을 생성합니다.
type Xor<A, B> = A extends B ? 0 : 1;
/*
A B Xor<A, B>
0 0 0
1 0 1
0 1 1
1 1 0
*/
type And<A, B> = A extends 1 ? B extends 1 ? 1 : 0 : 0;
/*
A B And<A, B>
0 0 0
1 0 0
0 1 0
1 1 1
*/
type Or<A, B> = A extends 1 ? 1 : B extends 1 ? 1 : 0;
/*
A B Or<A, B>
0 0 0
1 0 1
0 1 0
1 1 1
*/
둘째, 가산기 회로를 고려하십시오.
보시다시피 우리는 2개의 숫자의 2비트를 사용하고 캐리 인 및 리턴 결과 비트와 캐리 아웃을 사용해야 합니다.
type Sum<A, B, CIn> = Xor<Xor<A, B>, CIn>;
type COut<A, B, CIn> = Or<And<A, B>, And<Xor<A, B>, CIn>>;
마지막으로 가산기 유형을 만듭니다.
type Add<A, B, CIn = 0> =
A extends [...infer AN, infer AC]
? B extends [...infer BN, infer BC]
? [...Add<AN, BN, COut<AC, BC, CIn>>, Sum<AC, BC, CIn>]
: []
: [];
let d1: Add<[0], [1]>
// ^ = let d1: [1]
let d2: Add<[0, 1], [0, 1]>
// ^ = let d2: [1, 0]
let d3: Add<[0, 1, 1, 1], [0, 0, 0, 1]>
// ^ = let d3: [1, 0, 0, 0]
let d4: Add<[1, 1, 1, 1], [0, 0, 0, 1]>
// ^ = let d4: [0, 0, 0, 0]
playground
다른 이진 연산은 이러한 원칙을 사용하여 구현할 수 있습니다. 실제 프로젝트에서 이러한 유형이 필요합니까? 나는 그렇게 생각하지 않는다. 하지만 이러한 원칙이 정말 유용한 유형을 만드는 데 도움이 될 것이라고 생각합니다. 저를 구독하시면 흥미로운 유형의 TypeScript에 대해 자세히 알려 드리겠습니다.
Reference
이 문제에 관하여(TypeScript: 유형 기반 이진 가산기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bytimo/typescript-type-based-binary-adder-53i7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)