[typescript] 클래스 속성이 정수임을 어떻게 지정합니까?

저는 TypeScript로 실험하고 있으며 정수 여야하는 “ID”필드가있는 클래스를 만드는 과정에서 약간 혼란 스러웠습니다.

먼저 TypeScript 플러그인을 사용하는 Visual Studio 2012에서 intelliSense 형식 목록에 “int”가 표시됩니다. 하지만 “현재 범위에 ‘int’라는 이름이 존재하지 않습니다.”라는 컴파일 오류가 발생합니다.

언어 사양을 검토 한 결과 숫자, 문자열, 부울, null 및 정의되지 않은 기본 유형 만 표시됩니다. 정수 유형이 없습니다.

그래서 두 가지 질문이 남았습니다.

  1. 특정 필드가 단순히 “숫자”가 아니라 정수 (부동 소수점 또는 십진수가 아님)임을 클래스 사용자에게 어떻게 표시해야 합니까?

  2. 올바른 유형이 아닌 경우 인텔리 센스 목록에 “int”가 표시되는 이유는 무엇입니까?

업데이트 : 지금까지 얻은 모든 답변은 JavaScript에 int 유형이없는 방법에 대한 것입니다. 런타임에 int 유형을 적용하기가 어려울 것입니다. 이 필드가 정수 여야한다는 내 클래스의 사용자에게 주석을 제공하는 TypeScript 방법이 있는지 묻습니다. 특정 형식에 대한 의견일까요?



답변

  1. 숫자가 정수인지 부동 소수점인지를 지정하는 직접적인 방법은 없다고 생각합니다. TypeScript 사양 섹션 3.2.1에서 다음을 볼 수 있습니다.

    “… 숫자 기본 유형은 유사한 이름의 JavaScript 기본 유형에 해당하며 배정 밀도 64 비트 형식 IEEE 754 부동 소수점 값을 나타냅니다 …”

  2. intVisual Studio intelliSense의 버그 라고 생각 합니다. 정답은 number입니다.


답변

TypeScript는 int라는 개념이없는 JavaScript의 상위 집합입니다. 부동 소수점이있는 숫자의 개념 만 있습니다.

철학적으로 TypeScript int 유형에 대해 정수만 적용하기 위해 컴파일러가 수행해야하는 작업의 양은 잠재적으로 방대 할 수 있으며 경우에 따라 컴파일 타임에 정수만 할당되도록 보장 할 수 없습니다. intTypeScript에를 안정적으로 추가 할 수없는 이유 입니다.

Visual Studio에서 처음에 intelliSense를 가져 오면 도구가 제공 할 항목을 결정할 수 없으므로 int를 포함한 모든 것을 얻을 수 있지만 알려진 유형의 항목을 처리하면 합리적인 intelliSense를 얻게됩니다.

var myInt: number;
var myString: string;

myInt. // toExponential, toFixed, toPrecision, toString
myString. // charAt, charCodeAt, concat, indexOf, lastIndexOf, length and many more...


답변

더 없다 integer거나 float하지만 number형 타이프에서 자바 스크립트처럼. 그러나 프로그래머에게 integer유형을 예상한다고 말하고 싶다면 다음 과 같은 유형 별칭 을 사용할 수 있습니다.

type integer = number;
type float = number;

// example:
function setInt(id: integer) {}

그러나 이것은 여전히 number유형이며 얻을 수 있습니다 float.

문서 설명의 일부 :
“앨리어싱은 실제로 새 유형을 생성하지 않습니다. 해당 유형을 참조하기 위해 새 이름을 생성합니다. 프리미티브에 별칭을 지정하는 것은 문서 형식으로 사용할 수는 있지만 그다지 유용하지는 않습니다.”


답변

TypeScript에서는 마커를 사용하여 불투명 유형이라고하는 것을 근사 할 수 있습니다.

// Helper for generating Opaque types.
type Opaque<T, K> = T & { __opaque__: K };

// 2 opaque types created with the helper
type Int = Opaque<number, 'Int'>;
type ID = Opaque<number, 'ID'>;

// using our types to differentiate our properties even at runtime
// they are still just numbers
class Foo {
    someId: ID;
    someInt: Int;
}

let foo = new Foo();

// compiler won't let you do this due to or markers
foo.someId = 2;
foo.someInt = 1;

// when assigning, you have to cast to the specific type
// NOTE: This is not completely type safe as you can trick the compiler 
// with something like foo.someId = 1.45 as ID and it won't complain.
foo.someId = 2 as ID;
foo.someInt = 1 as Int;

// you can still consume as numbers
let sum: number = foo.someId + foo.someInt;

이렇게하면 속성이 예상하는 유형에 대해 코드에서 더 명확하게 할 수 있으며 컴파일러는 캐스트없이 기본 값을 할당하는 것을 허용하지 않습니다. 이는 추가 .js 출력을 생성하지 않으며, 기반이되는 유형으로 값을 계속 소비하고 사용할 수 있습니다. 이 예에서는 숫자를 사용하고 있지만 문자열 및 기타 유형에도 사용할 수 있습니다.

이 예제에서 Int 또는 Id가 아닌 것을 받아들이도록 컴파일러를 속일 수 있지만 Int 또는 이와 유사한 것으로 1.45를 할당하려는 경우 튀어 나와야합니다. 또한 런타임 유효성 검사를 제공하기 위해 값을 만드는 데 사용하는 도우미 함수를 만드는 옵션도 있습니다.

“표시된”유형을 생성 할 수있는 여러 가지 방법이 있습니다. 다음은 좋은 기사입니다 : https://michalzalecki.com/nominal-typing-in-typescript/


답변

이것은 나에게 Google의 최고 결과이므로 찾은 솔루션을 제공해야한다고 생각합니다.

사용 bigint

이제 2020 년 bigint이되었고 승인되었으므로 언급 할 가치가 있습니다. 간단히 아래를 수행 할 수 있습니다. 조심하십시오 bigint의가에 비해 큰 성능 저하와 함께 number.

const myNumber: bigint = 10n

공칭 형 / 태그 형 / 불투명 형 사용

대안은 명목 유형을 사용하는 것이지만, 인체 공학적이지 않고보다 빠른지 확실 bigint하지 않지만 패턴은 number. TypeScript는 이에 대한 “일급”지원이 없으므로 건방진 해킹을해야합니다. newtype-ts이와 같은 일반적인 유형을 포함 하는이 호출에 대한 라이브러리가 Integer있으므로 그냥 사용하고 싶을 수도 있지만 아래에서 작동하는 방법을 설명하겠습니다.

먼저 integer유형 을 정의합니다 .

const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }

이는 TAG우리가 우연히 동일한 키를 가진 객체를 만들지 않도록 고유 한 값을 가지도록 보장하고 동일한 이유로 필드도 고유 한 기호로 만듭니다. 이제 정수에는 실제로이 개체 필드가 ​​없지만 괜찮습니다.

이것으로 당신은 여전히 추가 할 수 있습니다 integernumber사용 +. 안좋다. 따라서 함수로 유형 시스템을 마사지하여 여기에서 인수에 유형 안전을 적용 할 수 있습니다. 그냥 가드라고 부르겠습니다. 보시 integer다시피 s 에만 국한되지 않습니다. 더 불투명 한 유형을 만들고 이것을 다시 사용할 수 있습니다.

type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)

당신이 그것을 number

const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)

아래와 같은 오류가 발생합니다.

Argument of type '10' is not assignable to parameter of type 'integer'.
  Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)

여기서 반환 유형을 적용하지 않고 (을 사용해야하기 때문에 as integer)와 같은 일부 연산자 /는 부동 소수점 숫자를 반환하므로 런타임 검사를 수행하거나 Math.round의 특수 버전에를 추가하고 싶을 guard것입니다. 당신은 두 개의 별도의 숫자 형식을 사용하려고하지 않을 수 있도록 – 당신이 상상 GBP하고 USD그를 추가하려고, 그 가능성이 당신이 의도하지 않을 것입니다.


답변

글쎄, 보시다시피 typescript는 자바 스크립트 언어와 같은 부동 데이터 유형이 아닙니다. 만 가지고있는 number모든를 커버 그 intdouble동시에; 아마도 당신은 숫자를 취하는 함수를 만들고 그것이 오류 / 성공의 경우 어떤 상태를 반환함으로써 그것이 int또는 인지 확인해야합니다 double. 수업 방법으로 다음과 같은 것 :

function SetN(x:number) {
   var is_int = parseInt(x) === parseFloat(x);
   if(is_int) this.n = x;
   return is_int;
}

//..
y = 10.5;
if(SetN(y)) {
  //OK
} else {
   //error not set y isn't a int
}

참고 : 작동하지 않습니다. 10.0예 를 들어 실제로 원하지 않는 경우 문자열로 변환하고 ..


답변

int이전 버전의 javascript (원하는 경우 ECMAScript) 에서 향후 사용 키워드를 위해 예약되었습니다 . 그러나 지금은 유효한 단어입니다 ( “지금”이 “최신 사양”과 동일 함).

예를 들어, 262 년에는 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf 에서 여전히 예약되었습니다 .

int데이터 유형이 구현되었지만 모든 컴파일 타임 유형 검사 및 캐스팅 규칙을 사용할 수 있도록 typescript에 멋지게 추가 할 수 있습니다.