টাইপস্ক্রিপ্টে স্থির দৈর্ঘ্যের অ্যারে কীভাবে ঘোষণা করবেন


112

টাইপস্ক্রিপ্ট প্রকারের আশেপাশে আমার জ্ঞানের অভাব প্রদর্শনের ঝুঁকিতে - আমার নিম্নলিখিত প্রশ্ন রয়েছে।

আপনি যখন এই জাতীয় অ্যারের জন্য কোনও প্রকারের ঘোষণা করেন ...

position: Array<number>;

... এটি আপনাকে নির্বিচারে দৈর্ঘ্যের সাথে একটি অ্যারে তৈরি করতে দেয়। তবে, আপনি যদি একটি নির্দিষ্ট দৈর্ঘ্য সহ 3 টি x, y, z উপাদানগুলির সাথে সংযুক্ত একটি অ্যারে চান তবে আপনি একটি নির্দিষ্ট দৈর্ঘ্যের অ্যারের জন্য একটি টাইপ তৈরি করতে পারেন, এরকম কিছু?

position: Array<3>

কোন সহায়তা বা ব্যাখ্যা প্রশংসা!

উত্তর:


178

জাভাস্ক্রিপ্ট অ্যারেতে এমন কনস্ট্রাক্টর রয়েছে যা অ্যারের দৈর্ঘ্য গ্রহণ করে:

let arr = new Array<number>(3);
console.log(arr); // [undefined × 3]

যাইহোক, এটি কেবলমাত্র প্রাথমিক আকার, এটি পরিবর্তন করতে কোনও বাধা নেই:

arr.push(5);
console.log(arr); // [undefined × 3, 5]

টাইপস্ক্রিপ্টে টুপল প্রকার রয়েছে যা আপনাকে একটি নির্দিষ্ট দৈর্ঘ্য এবং প্রকার সহ একটি অ্যারে সংজ্ঞা দেয়:

let arr: [number, number, number];

arr = [1, 2, 3]; // ok
arr = [1, 2]; // Type '[number, number]' is not assignable to type '[number, number, number]'
arr = [1, 2, "3"]; // Type '[number, number, string]' is not assignable to type '[number, number, number]'

21
টিউপল প্রকারগুলি কেবলমাত্র প্রাথমিক আকারটি পরীক্ষা করে, তাই আপনি arrএটি শুরু করার পরেও আপনার সীমাহীন পরিমাণ "নম্বর" চাপতে পারেন।
বেনজামিনজ

4
সত্য, এটি রানওটাইমে এখনও জাভাস্ক্রিপ্ট সেই সময়ে "কিছু যায়" goes কমপক্ষে টাইপ
স্ক্রিপ্ট ট্রান্সপ্লারটি

7
যদি আমি 50 টির মতো বড় অ্যারের আকার চাই, তবে পুনরাবৃত্ত প্রকারের মতো অ্যারের আকার নির্দিষ্ট করার মতো কোনও উপায় আছে [number[50]], যাতে [number, number, ... ]50 বার লেখার প্রয়োজন হয় না ?
ভিক্টর জামামানিয়ান

4
কিছু মনে করবেন না, এই সম্পর্কে একটি প্রশ্ন খুঁজে। stackoverflow.com/questions/52489261/...
ভিক্টর Zamanian

4
@ ভিক্টরজাম্যানিয়ান ঠিক আপনারা যেমন সচেতন হন, ছেদ করার ধারণাটি আপনি {length: TLength}টাইপ করা ছাড়িয়ে গেলে কোনও টাইপ স্ক্রিপ্ট ত্রুটি সরবরাহ করে না TLength। আমি এখনও আকার-প্রয়োগকারী এন-দৈর্ঘ্যের ধরণের সিনট্যাক্সটি পাইনি।
লুকাস মরগান

26

টিপল পদ্ধতির:

এই সমাধানটি টিপলসের ভিত্তিতে একটি কঠোর ফিক্সডলেংথারি (ak.a. સીলেডআরে) ধরণের স্বাক্ষর সরবরাহ করে।

সিনট্যাক্স উদাহরণ:

// Array containing 3 strings
let foo : FixedLengthArray<[string, string, string]> 

এটি সীমাবদ্ধতার বাইরে সূচি অ্যাক্সেসকে বাধা দেয় বিবেচনা করে এটি সবচেয়ে নিরাপদ পদ্ধতি ।

বাস্তবায়ন :

type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift' | number
type ArrayItems<T extends Array<any>> = T extends Array<infer TItems> ? TItems : never
type FixedLengthArray<T extends any[]> =
  Pick<T, Exclude<keyof T, ArrayLengthMutationKeys>>
  & { [Symbol.iterator]: () => IterableIterator< ArrayItems<T> > }

পরীক্ষা:

var myFixedLengthArray: FixedLengthArray< [string, string, string]>

// Array declaration tests
myFixedLengthArray = [ 'a', 'b', 'c' ]  // ✅ OK
myFixedLengthArray = [ 'a', 'b', 123 ]  // ✅ TYPE ERROR
myFixedLengthArray = [ 'a' ]            // ✅ LENGTH ERROR
myFixedLengthArray = [ 'a', 'b' ]       // ✅ LENGTH ERROR

// Index assignment tests 
myFixedLengthArray[1] = 'foo'           // ✅ OK
myFixedLengthArray[1000] = 'foo'        // ✅ INVALID INDEX ERROR

// Methods that mutate array length
myFixedLengthArray.push('foo')          // ✅ MISSING METHOD ERROR
myFixedLengthArray.pop()                // ✅ MISSING METHOD ERROR

// Direct length manipulation
myFixedLengthArray.length = 123         // ✅ READ-ONLY ERROR

// Destructuring
var [ a ] = myFixedLengthArray          // ✅ OK
var [ a, b ] = myFixedLengthArray       // ✅ OK
var [ a, b, c ] = myFixedLengthArray    // ✅ OK
var [ a, b, c, d ] = myFixedLengthArray // ✅ INVALID INDEX ERROR

(*) এই সমাধানটির কাজ করার জন্য noImplicitAnyটাইপস্ক্রিপ্ট কনফিগারেশন নির্দেশকে সক্ষম করার প্রয়োজন হয় (সাধারণত প্রস্তাবিত অনুশীলন)


অ্যারে (ইশ) পদ্ধতির:

এই দ্রবণটি Arrayএকটি অতিরিক্ত দ্বিতীয় প্যারামিটার (অ্যারে দৈর্ঘ্য) গ্রহণ করে, প্রকারের বৃদ্ধি হিসাবে কাজ করে । টিপল ভিত্তিক সমাধানের মতো কঠোর এবং নিরাপদ নয় ।

সিনট্যাক্স উদাহরণ:

let foo: FixedLengthArray<string, 3> 

মনে রাখবেন যে এই পদ্ধতির আপনাকে ঘোষিত সীমানাগুলির বাইরে কোনও সূচি অ্যাক্সেস করা থেকে বিরত করবে না এবং এর জন্য একটি মান সেট করবে।

বাস্তবায়ন :

type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' |  'unshift'
type FixedLengthArray<T, L extends number, TObj = [T, ...Array<T>]> =
  Pick<TObj, Exclude<keyof TObj, ArrayLengthMutationKeys>>
  & {
    readonly length: L 
    [ I : number ] : T
    [Symbol.iterator]: () => IterableIterator<T>   
  }

পরীক্ষা:

var myFixedLengthArray: FixedLengthArray<string,3>

// Array declaration tests
myFixedLengthArray = [ 'a', 'b', 'c' ]  // ✅ OK
myFixedLengthArray = [ 'a', 'b', 123 ]  // ✅ TYPE ERROR
myFixedLengthArray = [ 'a' ]            // ✅ LENGTH ERROR
myFixedLengthArray = [ 'a', 'b' ]       // ✅ LENGTH ERROR

// Index assignment tests 
myFixedLengthArray[1] = 'foo'           // ✅ OK
myFixedLengthArray[1000] = 'foo'        // ❌ SHOULD FAIL

// Methods that mutate array length
myFixedLengthArray.push('foo')          // ✅ MISSING METHOD ERROR
myFixedLengthArray.pop()                // ✅ MISSING METHOD ERROR

// Direct length manipulation
myFixedLengthArray.length = 123         // ✅ READ-ONLY ERROR

// Destructuring
var [ a ] = myFixedLengthArray          // ✅ OK
var [ a, b ] = myFixedLengthArray       // ✅ OK
var [ a, b, c ] = myFixedLengthArray    // ✅ OK
var [ a, b, c, d ] = myFixedLengthArray // ❌ SHOULD FAIL

4
ধন্যবাদ! তবে, ত্রুটি না পেয়ে অ্যারের আকার পরিবর্তন করা এখনও সম্ভব।
এডওয়ার্ড

4
var myStringsArray: FixedLengthArray<string, 2> = [ "a", "b" ] // LENGTH ERROR2 এখানে 3 হওয়া উচিত বলে মনে হচ্ছে?
কিওয়ারটি

আমি কঠোর সমাধান সঙ্গে বাস্তবায়ন আপডেট করেছি যে প্রতিরোধ অ্যারের দৈর্ঘ্য পরিবর্তন
colxi

@ কলসি কি এমন একটি বাস্তবায়ন সম্ভব যা ফিক্সডলংথআরাই থেকে অন্য ফিক্সডলিংথআর্রে ম্যাপিংয়ের অনুমতি দেয়? আমার অর্থের একটি উদাহরণ:const threeNumbers: FixedLengthArray<[number, number, number]> = [1, 2, 3]; const doubledThreeNumbers: FixedLengthArray<[number, number, number]> = threeNumbers.map((a: number): number => a * 2);
অ্যালেক্স ম্যালকম

@ অ্যালেক্সমালকম আমার ভয় হচ্ছে mapযে এটির ফলাফলের জন্য জেনেরিক অ্যারে স্বাক্ষর সরবরাহ করবে। আপনার ক্ষেত্রে সম্ভবত একটি number[]প্রকার
colxi

8

আসলে, আপনি বর্তমান টাইপ স্ক্রিপ্ট দিয়ে এটি অর্জন করতে পারেন:

type Grow<T, A extends Array<T>> = ((x: T, ...xs: A) => void) extends ((...a: infer X) => void) ? X : never;
type GrowToSize<T, A extends Array<T>, N extends number> = { 0: A, 1: GrowToSize<T, Grow<T, A>, N> }[A['length'] extends N ? 0 : 1];

export type FixedArray<T, N extends number> = GrowToSize<T, [], N>;

উদাহরণ:

// OK
const fixedArr3: FixedArray<string, 3> = ['a', 'b', 'c'];

// Error:
// Type '[string, string, string]' is not assignable to type '[string, string]'.
//   Types of property 'length' are incompatible.
//     Type '3' is not assignable to type '2'.ts(2322)
const fixedArr2: FixedArray<string, 2> = ['a', 'b', 'c'];

// Error:
// Property '3' is missing in type '[string, string, string]' but required in type 
// '[string, string, string, string]'.ts(2741)
const fixedArr4: FixedArray<string, 4> = ['a', 'b', 'c'];

4
যখন উপাদানগুলির সংখ্যা একটি পরিবর্তনশীল হয় তখন আমি এটি কীভাবে ব্যবহার করব? যদি আমার কাছে সংখ্যার ধরণ হিসাবে N এবং সংখ্যা হিসাবে "num" থাকে, তবে কনস্ট অ্যারে: ফিক্সডআরে <সংখ্যা, এন> = অ্যারে.ফর্ম (নতুন অ্যারে (সংখ্যা), (x, i) => i); আমাকে "টাইপ ইনস্ট্যান্টেশন অত্যধিক গভীর এবং সম্ভবত অসীম" দেয়।
মিশা সোয়াব

4
@ মিছাচাবব দুর্ভাগ্যক্রমে মনে হচ্ছে এটি কেবল অপেক্ষাকৃত কম সংখ্যক সাথেই কাজ করে। অন্যথায় এটি "অত্যধিক পুনরাবৃত্তি" বলে। একই ক্ষেত্রে আপনার ক্ষেত্রে প্রযোজ্য। আমি এটি পুরোপুরি পরীক্ষা করিনি :(।
টমাসজ গাওয়েল

আমার কাছে ফিরে আসার জন্য ধন্যবাদ! আপনি যদি ভেরিয়েবল দৈর্ঘ্যের জন্য কোনও সমাধান পান তবে দয়া করে আমাকে জানান।
মিচা সোয়াব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.