Bir sınıf özelliğinin tamsayı olduğunu nasıl belirtirsiniz?


111

Üzerinde deneyler yapıyorum TypeScriptve IDolması gereken bir alanı olan bir sınıf oluşturma sürecinde integerbiraz kafam karıştı.

Öncelikle, TypeScript eklentisine sahip Visual Studio 2012'de intintelliSense türlerinin listesinde görüyorum . Ama şunu söyleyen bir derleme hatası alıyorum:

'int' adı mevcut kapsamda mevcut değil.

Ben dil özellikleri inceledikten ve yalnızca aşağıdaki ilkel türlerini görmek: number, string, boolean, null, ve undefined. integerTür yok .

Öyleyse, iki soruyla kaldım:

  1. Nasıl belirtmek gerekir benim sınıfının kullanıcıları belirli bir alan adil olmadığını bir numberancak integer(ve asla bir floatingnokta veya decimalsayı)?

  2. intGeçerli bir tür değilse neden intellisense listesinde görüyorum ?

Güncelleme: Şimdiye kadar aldığım tüm cevaplar, nasıl JavaScriptbir int türüne sahip olmadığıyla ilgili int, çalışma zamanında bir türü uygulamak zor olurdu ... Bunların hepsini biliyorum. Bir olup olmadığını soruyorum TypeScriptbu alan bir olması gerektiğini dersime kullanıcılarına bir şerh sağlamak için bir yol integer. Belki belirli bir formatın bir yorumu?


6
Hayır, uygulamamda da geçerli bir kimlik değil. 10, geçerli bir kimlik olacaktır.
Josh


Bir alanı doğrulamanın ve yalnızca tamsayı değerlerinin kabul edildiğinden emin olmanın bir yolu, herhangi bir olası giriş değerini önce String'e atan, a değerinin ondalık noktası olmadığını kontrol etmek için RegEx kullanan bir doğrulama yöntemi oluşturmaktır. b.) ondalık nokta varsa, sonraki tüm karakterler sıfırdır. Daha sonra, yöntem sayı türüne geri döner ve sonuç, kısıtlama gerektiren alana iletilir.
Nathan Toulbert

Yanıtlar:


110
  1. Bir sayının tam sayı mı yoksa kayan nokta mı olduğunu belirlemenin doğrudan bir yolu olmadığını düşünüyorum. TypeScript belirtimi bölümünde 3.2.1 şunları görebiliriz:

    "... Sayı temel türü, benzer şekilde adlandırılmış JavaScript ilkel türüne karşılık gelir ve çift duyarlıklı 64 bit biçimindeki IEEE 754 kayan nokta değerlerini temsil eder ..."

  2. intVisual Studio intelliSense'te bir hata olduğunu düşünüyorum . Doğru olan number.


2
Sanırım cevap bu. 1) Sayısal türler için basitçe "sayı" dan daha ayrıntılı bir şey belirtemezsiniz veya bunu yapmak için tanınmış herhangi bir ek açıklama yoktur; ve 2) VS eklentisinde, belki de ECMA 262 ayrılmış anahtar kelimeler listesine ("int" içeren) dayalı olarak geçersiz türler öneren bir hata var
Josh

Statik int türü uygulamak mümkündür, ancak bunu yapmamayı seçerler. Belki de uygulamanın çok karmaşık olduğunu düşünüyorlar?
trusktr

29

TypeScript, int kavramına sahip olmayan bir JavaScript üst kümesidir. Yalnızca kayan noktası olan bir sayı kavramına sahiptir.

Felsefi olarak, bir TypeScript int türü için yalnızca tam sayıları zorlamak için derleyicinin yapması gereken iş miktarı, potansiyel olarak çok büyük olabilir ve bazı durumlarda, derleme zamanında yalnızca tam sayıların atanmasını sağlamak yine de mümkün olmayabilir. bu nedenle intTypeScript'e güvenilir bir şekilde bir ekleme yapmak mümkün değildir .

Visual Studio'da ilk olarak intelliSense aldığınızda, aracın ne sağlayacağını belirlemesi mümkün değildir, bu nedenle int dahil her şeyi alırsınız - ancak bilinen türde bir şeyle uğraştığınızda, mantıklı bir intelliSense elde edersiniz.

Örnekler

var myInt: number;
var myString: string;

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

2
Ancak bu, kullanıcıların uygun alan türünü bilmeleri için sınıfıma nasıl not ekleyeceğime dair sorumun yanıtını vermiyor. Ayrıca, "int" hiçbir zaman geçerli bir tür değilse, neden "her şey" listesine dahil edildi?
Josh

Bunu public myVariable : number;bir sayı olarak bildirmek için kullanırsınız . intJavaScript'te ayrılmış bir kelimedir, bu nedenle her şey listesinde görünür. JavaScript int hakkında bilgi: javascript.about.com/od/reference/g/rint.htm
Fenton

public discountPercent : numberkullanıcıya ondalık (ör.% 10 için 0.10) veya tam sayı (ör.% 10 için 10) olması gerektiğini söylemez. Kütüphane kullanıcısına neyin geçerli neyin geçersiz olduğunu açıklamanın bir yolu yok mu?
Josh

@JoshuaBeall - JavaScript veya TypeScript'te ondalık ve tam sayı arasında bir fark yoktur. Sayı türü her ikisi için de kullanılır.
Fenton

1
@Fenton dediniz: "TypeScript, bir int kavramı olmayan JavaScript'in bir üst kümesidir. Sadece kayan noktası olan bir sayı kavramı vardır." Doğru, ancak aslında intonlar yapmamayı seçtikleri halde TypeScript'te bir tür uygulamak mümkündür .
trusktr

15

TypeScript'te JavaScript'te olduğu gibi yok integerveya floatama numbertürü yok . Eğer söyle programcı Ama isterseniz beklediklerini integerkullanmak deneyebilirsiniz yazın Tipi diğer adları gibi

type integer = number;
type float = number;

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

ama bu hala numberyazın ve alabilirsiniz float.

Dokümantasyondaki açıklamanın bir kısmı:
"Takma ad aslında yeni bir tür oluşturmaz - bu türe başvurmak için yeni bir ad oluşturur. Bir ilkeli takma ad, bir belge biçimi olarak kullanılabilir olsa da, çok kullanışlı değildir."


8

TypeScript'te, bazen bir işaretçi kullanarak opak tip olarak adlandırılan şeyi tahmin edebilirsiniz.

// 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;

Bunu yapmak, kodunuzda mülklerinizin ne türler beklediği konusunda daha açık olmanızı sağlar ve derleyici, dönüştürme olmadan ilkel bir değer atamanıza izin vermez. Bu, herhangi bir ek .js çıktısı üretmez ve yine de değerleri, dayandıkları türde tüketebilir ve kullanabilirsiniz. Bu örnekte sayıları kullanıyorum, ancak dizelerde ve diğer türlerde de kullanabilirsiniz.

Bu örnekte derleyiciyi hala Int veya Id olmayan bir şeyi kabul etmesi için kandırabilirsiniz, ancak 1.45'i Int veya buna benzer bir şey olarak atamaya çalışıyorsanız, atlaması gerekir. Ayrıca, çalışma zamanı doğrulaması sağlamak üzere değerlerinizi oluşturmak için kullanacağınız yardımcı işlevler oluşturma seçeneğiniz de vardır.

"İşaretli" türler oluşturmanın birkaç farklı yolu vardır. İşte güzel bir makale: https://michalzalecki.com/nominal-typing-in-typescript/


Başka bir yerde söylendiği gibi, bunun gerçek kullanılabilirliği bir şekilde sorgulanabilir, ancak bir daktilo ve / veya Casting Helper ekleyerek daha da ileri gidebilirsiniz; bu, Int örneği gibi bazı şeyler için kolay ve diğerleri için neredeyse imkansızdır - gibi kimlik örneği: // @ts-ignore const isInt = (val: number | Int): val is Int => !(val % 1); const Integer = (val: number): Int => Math.round(val) as any;
Sam96

5

Bu benim için Google'daki en iyi sonuç, bu yüzden bulduğum çözümleri sağlamam gerektiğini düşünüyorum.

Kullanma bigint

Şimdi 2020 olduğuna ve bigintkabul edildiğine göre, sözünü hak ediyor. Aşağıdakileri kolayca yapabilirsiniz. A bigintile karşılaştırıldığında daha büyük bir performans etkisine sahip olduğuna dikkat edin number.

const myNumber: bigint = 10n


Nominal tip / etiketli tip / opak tip kullanma

Bir alternatif, nominal bir tür kullanmaktır, ancak tartışmalı olarak daha az ergonomiktir ve bundan daha hızlı olup olmadığından emin değilim bigint, ancak kalıp sadece herhangi bir türe genellemez number. TypeScript, bunun için "birinci sınıf" desteğe sahip değildir, bu yüzden arsız bir hack yapmanız gerekir. Bunun newtype-tsgibi yaygın türleri içeren bir kitaplık var, bu Integernedenle sadece onu kullanmak isteyebilirsiniz, ancak aşağıdaki çalışmaları açıklayacağım.

Başlamak için integertürü tanımlıyoruz .

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

TAGYanlışlıkla aynı anahtarla bir nesne yapmazlar böylece olmasını sağlar biz farklı bir değere sahip ve aynı sebepten dolayı eşsiz bir sembol de alan olun. Şimdi, tamsayınız aslında bu nesne alanına sahip olmayacak ama sorun değil.

Bununla hala ekleyebilir integeriçin numberkullanıyor +. İyi değil. Böylece, tür sistemini bir işlevle masaj yaparak buradaki argümanlarda tür güvenliğini uygulayabilirsiniz. Ben sadece ona koruma diyeceğim ve gördüğünüz gibi, bu, integers'ye özgü değil - daha opak tipler yapabilir ve bunu tekrar kullanabilirsiniz.

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

Eğer onu aramaya çalışırsan number

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

aşağıdaki gibi bir hata alacaksın

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

Burada dönüş türünü zorlamadığınızı unutmayın (çünkü kullanmanız gerekir as integer) ve bazı operatörler /kayan nokta sayılarını döndürecek, bu nedenle muhtemelen çalışma zamanı kontrolleri yapmak veya Math.roundözel bir sürümüne bir eklemek isteyeceksiniz guard, ancak bu en azından birlikte iki ayrı sayısal türleri kullanmak çalışmıyoruz sağlamak - sahip hayal GBPve USDve bu eklemeyi deneyin, muhtemelen ne amaçladığınız olmaz.


2

Gördüğünüz gibi, typcript javascript dili gibi veri türlerini kaydırmaz. Sadece numberhepsini kapsayan intve doubleaynı anda var; belki de bir sayıyı alan bir işlev yapmalı ve bunun bir intveya olup olmadığını kontrol etmelisiniz double, hata / başarı durumunda bir durum döndürerek. Sınıfınızın yöntemi olarak buna benzer bir şey:

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
}

Not: bu işe yaramaz, 10.0örneğin gerçekten istemiyorsanız, onu dizgeye dönüştürmeli ve a bulmaya çalışmalısınız ..


Bu, çalışma zamanı yaptırımına yardımcı olabilir, ancak öncelikle kullanıcıya hangi sayıların geçerli olduğunu bildirmekle ilgileniyorum.
Josh

1

intjavascript'in önceki sürümlerinde gelecekteki kullanım için ayrılmış anahtar kelime (isterseniz ECMAScript) . Ama şimdi geçerli bir kelimedir (burada "şimdi", "en son spesifikasyondaki" ile eşittir).

Örneğin, 262'de hala rezerve edildi, http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

Bir intveri türünün uygulanmış olması, ancak tüm derleme zamanı tür denetimi ve çevrim kurallarının kullanılabilir olması typcript'e güzel bir katkı sağlar .


Belki de zeka, derleyici tarafından tanınmasa bile bu "ayrılmış kelimeyi" alıyor?
Josh

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.