টাইপস্ক্রিপ্ট সহ ইন্টারফেস টাইপ চেক


293

এই প্রশ্নটি টাইপস্ক্রিপ্টের সাথে শ্রেণীর ধরণের চেকের সরাসরি অ্যানালগন

রানটাইমে আমাকে খুঁজে বের করতে হবে যদি কোনও টাইপের পরিবর্তক কোনও ইন্টারফেস প্রয়োগ করে। আমার কোডটি এখানে:

interface A{
    member:string;
}

var a:any={member:"foobar"};

if(a instanceof A) alert(a.member);

আপনি যদি টাইপ স্ক্রিপ্ট খেলার মাঠে এই কোডটি প্রবেশ করেন, শেষ লাইনটি একটি ত্রুটি হিসাবে চিহ্নিত করা হবে, "এ নামটি বর্তমান সুযোগে বিদ্যমান নেই"। তবে এটি সত্য নয়, বর্তমান সুযোগে নামটি বিদ্যমান। এমনকি আমি var a:A={member:"foobar"};সম্পাদকের কোনও অভিযোগ ছাড়াই পরিবর্তনশীল ঘোষণাটিও পরিবর্তন করতে পারি । ওয়েব ব্রাউজ করার পরে এবং এসও-তে অন্য প্রশ্নটি সন্ধান করার পরে আমি ইন্টারফেসটি একটি শ্রেণিতে পরিবর্তিত করেছিলাম তবে তারপরে উদাহরণগুলি তৈরি করতে আমি অবজেক্ট লিটারাল ব্যবহার করতে পারি না।

আমি আশ্চর্য হয়েছি কীভাবে এ জাতীয় প্রকারটি এভাবে বিলুপ্ত হতে পারে তবে উত্পন্ন জাভাস্ক্রিপ্টে একবার দেখে সমস্যাটি ব্যাখ্যা করা হয়েছে:

var a = {
    member: "foobar"
};
if(a instanceof A) {
    alert(a.member);
}

ইন্টারফেস হিসাবে এটির কোনও প্রতিনিধিত্ব নেই, সুতরাং কোনও রানটাইম ধরণের চেক সম্ভব নয়।

আমি বুঝতে পারি যে গতিশীল ভাষা হিসাবে জাভাস্ক্রিপ্টটির ইন্টারফেসের কোনও ধারণা নেই। ইন্টারফেসের জন্য চেক টাইপ করার কোনও উপায় আছে?

টাইপস্ক্রিপ্ট খেলার মাঠের স্বতঃপূরণ প্রকাশ করে যে টাইপস্ক্রিপ্ট এমনকি একটি পদ্ধতিও সরবরাহ করে implements। আমি কীভাবে এটি ব্যবহার করতে পারি?


4
জাভাস্ক্রিপ্টের ইন্টারফেসের কোনও ধারণা নেই, তবে এটি এটি একটি গতিশীল ভাষা বলে নয়। কারণ ইন্টারফেসগুলি এখনও কার্যকর হয়নি।
trusktr

হ্যাঁ, তবে আপনি পরিবর্তে ইন্টারফেসটি ক্লাস ব্যবহার করতে পারেন। এই উদাহরণটি দেখুন ।
আলেক্সি বারানোশনিকভ 11

স্পষ্টত 2017 এ নয় Super এখন খুব প্রাসঙ্গিক প্রশ্ন।
doublejosh

উত্তর:


220

আপনি instanceofকীওয়ার্ড ব্যতীত যা চান তা অর্জন করতে পারেন কারণ আপনি এখন কাস্টম টাইপ গার্ডগুলি লিখতে পারেন:

interface A{
    member:string;
}

function instanceOfA(object: any): object is A {
    return 'member' in object;
}

var a:any={member:"foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}

প্রচুর সদস্য

কোনও বস্তু আপনার ধরণের সাথে মেলে কিনা তা নির্ধারণ করতে আপনাকে যদি অনেক সদস্যের পরীক্ষা করতে হয় তবে আপনি পরিবর্তে একজন বৈষম্যমূলককে যুক্ত করতে পারেন। নীচে সর্বাধিক প্রাথমিক উদাহরণ, এবং আপনার নিজের বৈষম্যমূলকদের পরিচালনা করা প্রয়োজন ... আপনি নকল বৈষম্যমূলক আচরণ এড়ানোর জন্য আপনার নিদর্শনগুলির আরও গভীর হওয়া দরকার।

interface A{
    discriminator: 'I-AM-A';
    member:string;
}

function instanceOfA(object: any): object is A {
    return object.discriminator === 'I-AM-A';
}

var a:any = {discriminator: 'I-AM-A', member:"foobar"};

if (instanceOfA(a)) {
    alert(a.member);
}

85
"একটি ইন্টারফেস রানটাইম চেক করার কোন উপায় নেই।" আছে, যে কোনও কারণেই তারা এখনও এটি বাস্তবায়ন করেনি।
trusktr

16
এবং যদি ইন্টারফেসের 100 সদস্য থাকে তবে আপনার সমস্ত 100 টি পরীক্ষা করা দরকার? FOOBAR।
জেনি ও'রিলি

4
সমস্ত 100 পরীক্ষা করার পরিবর্তে আপনি আপনার অবজেক্টে একজন বৈষম্যমূলককে যুক্ত করতে পারেন ...
ফেন্টন

7
এই বৈষম্যমূলক দৃষ্টান্ত (এখানে লিখিত হিসাবে) প্রসারিত ইন্টারফেস সমর্থন করে না। একটি প্রাপ্ত ইন্টারফেসটি যদি বেস ইন্টারফেসের উদাহরণ হিসাবে এটি পরীক্ষা করে তা মিথ্যা প্রত্যাবর্তন করে।
অ্যারোন

1
@ ফেন্টন সম্ভবত আমি এ সম্পর্কে যথেষ্ট জানি না, তবে ধরুন আপনার একটি ইন্টারফেস বি আছে যা ইন্টারফেস এ-তে প্রসারিত হয়েছে, আপনি isInstanceOfA(instantiatedB)সত্য ফিরে পেতে চাইবেন , তবে আপনি isInstanceOfB(instantiatedA)মিথ্যা ফিরতে চাইবেন । পরবর্তী ঘটনাটি ঘটানোর জন্য, বি এর বৈষম্যকারীকে কি 'আই-এএম-এ' হতে হবে না?
অ্যারন

87

টাইপস্ক্রিপ্ট 1.6 এ, ব্যবহারকারী-সংজ্ঞায়িত টাইপ গার্ড কাজটি করবে।

interface Foo {
    fooProperty: string;
}

interface Bar {
    barProperty: string;
}

function isFoo(object: any): object is Foo {
    return 'fooProperty' in object;
}

let object: Foo | Bar;

if (isFoo(object)) {
    // `object` has type `Foo`.
    object.fooProperty;
} else {
    // `object` has type `Bar`.
    object.barProperty;
}

এবং জো ইয়াং যেমন উল্লেখ করেছে: টাইপস্ক্রিপ্ট ২.০ থেকে আপনি ট্যাগ ইউনিয়ন প্রকারের সুবিধা নিতে পারেন।

interface Foo {
    type: 'foo';
    fooProperty: string;
}

interface Bar {
    type: 'bar';
    barProperty: number;
}

let object: Foo | Bar;

// You will see errors if `strictNullChecks` is enabled.
if (object.type === 'foo') {
    // object has type `Foo`.
    object.fooProperty;
} else {
    // object has type `Bar`.
    object.barProperty;
}

এবং এটি switchখুব কাজ করে।


1
এটি বরং কৌতূহলী দেখাচ্ছে। স্পষ্টতই কিছু ধরণের মেটা-তথ্য উপলব্ধ। কেন এই টাইপ-গার্ড সিনট্যাক্স দিয়ে এটি প্রকাশ করুন ose আইস ইনস্ট্যান্সফের বিপরীতে কোন বাধা কোন ফাংশন কাজের পাশে "অবজেক্ট ইজ ইন্টারফেস" করে? আরও স্পষ্টভাবে, আপনি যদি সরাসরি বিবৃতিতে "অবজেক্টটি ইন্টারফেস" ব্যবহার করতে পারেন? তবে যে কোনও ক্ষেত্রে, আমার কাছ থেকে অত্যন্ত আকর্ষণীয় বাক্য গঠন, +1।
lhk

1
@ এলএইচকে না, এ জাতীয় বিবৃতি নেই, এটি আরও একটি বিশেষ ধরণের মতো যা বলে যে শর্তাধীন শাখাগুলির ভিতরে কীভাবে সংকীর্ণ করা উচিত। টাইপস্ক্রিপ্টের "স্কোপ" এর কারণে, আমি বিশ্বাস করি এমনকি ভবিষ্যতে এমন বিবৃতি থাকবে না। মধ্যে আরেকটি বিভিন্ন object is typeএবং object instanceof classএটা কোন ব্যাপার না একটি প্লেইন বস্তু বা একটি ক্লাসের একটা নিদর্শন,: এটি শুধুমাত্র পরিবর্তে যেখানে একটি বস্তু থেকে আকৃতি পেতে পারি এর "আকৃতি" বজায় রাখে, যে, টাইপ করা বিষয় টাইপ কাঠামোগত হয়।
ভিলিকভেনে

2
কেবল একটি ভুল ধারণা পরিষ্কার করার জন্য এই উত্তরটি তৈরি করতে পারে: রানটাইমের সময় অবজেক্টের ধরণ বা তার ইন্টারফেস কেটে নেওয়ার মতো কোনও মেটা তথ্য নেই।
Mostruash

@ মোস্ট্রুশ হ্যাঁ, উত্তরটির দ্বিতীয়ার্ধটি সংকলন করা সত্ত্বেও রানটাইমে কাজ করবে না।
trusktr

4
ওহ, তবে, এটি অবশ্যই ধরে নিতে হবে যে রানটাইমের সময় এই বিষয়গুলি একটি typeসম্পত্তি নিয়ে তৈরি করা হবে । সেক্ষেত্রে এটি কাজ করে। এই উদাহরণটি এই সত্যটি দেখায় না।
trusktr

40

টাইপসক্রিপ্ট 2.0 ট্যাগযুক্ত ইউনিয়ন প্রবর্তন

প্রকারভেদ 2.0 বৈশিষ্ট্য

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape) {
    // In the following switch statement, the type of s is narrowed in each case clause
    // according to the value of the discriminant property, thus allowing the other properties
    // of that variant to be accessed without a type assertion.
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
    }
}

আমি ২.০ বিটা ব্যবহার করছি তবে ট্যাগ ইউনিয়ন কাজ করে না। <
টাইপস্ক্রিপ্টটি টুলস

নাইট বিল্ড সহ সংকলিত, তবে ইন্টেলিজেন্স কাজ করে না। এটি ত্রুটিগুলিও তালিকাবদ্ধ করে: সম্পত্তির প্রস্থ / আকার / ... 'স্কয়ার | প্রকারে বিদ্যমান নেই আয়তক্ষেত্র | ক্ষেত্রে বিবৃতি সার্কেল। তবে এটি সংকলন করে।
মকলা

23
এটি সত্যিই কেবল একটি বৈষম্যমূলক ব্যবহার করছে।
এরিক ফিলিপস

33

ব্যবহারকারী-সংজ্ঞায়িত টাইপ গার্ডগুলি সম্পর্কে কীভাবে? https://www.typescriptlang.org/docs/handbook/advanced-types.html

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function isFish(pet: Fish | Bird): pet is Fish { //magic happens here
    return (<Fish>pet).swim !== undefined;
}

// Both calls to 'swim' and 'fly' are now okay.

if (isFish(pet)) {
    pet.swim();
}
else {
    pet.fly();
}

3
অনুরূপ - এটা আমার প্রিয় জবাব stackoverflow.com/a/33733258/469777 কিন্তু যাদু স্ট্রিং যে minification ভালো জিনিস কারণে ভঙ্গ করতে পারে না।
স্টাফোর্ড উইলিয়ামস

1
এটি কোনও কারণে আমার পক্ষে কাজ করে নি তবে (pet as Fish).swim !== undefined;করেছে।
সাইবারমিউ

18

এটি এখন সম্ভব, আমি কেবল সংকলকটির একটি বর্ধিত সংস্করণ প্রকাশ করেছি TypeScriptযা সম্পূর্ণ প্রতিবিম্ব ক্ষমতা প্রদান করে। আপনি ক্লাসগুলি তাদের মেটাডেটা অবজেক্টগুলি থেকে ইনস্ট্যান্ট করতে পারেন, ক্লাস কন্সট্রাক্টরদের থেকে মেটাডেটা পুনরুদ্ধার করতে পারেন এবং রানটাইমে ইন্টারফেস / ক্লাস পরিদর্শন করতে পারেন। আপনি এটি এখানে পরীক্ষা করে দেখতে পারেন

ব্যবহারের উদাহরণ:

আপনার টাইপ স্ক্রিপ্ট ফাইলগুলির মধ্যে একটি ইন্টারফেস এবং একটি শ্রেণি তৈরি করুন যা এটি নীচের মতো প্রয়োগ করে:

interface MyInterface {
    doSomething(what: string): number;
}

class MyClass implements MyInterface {
    counter = 0;

    doSomething(what: string): number {
        console.log('Doing ' + what);
        return this.counter++;
    }
}

এখন কিছু প্রয়োগ করা ইন্টারফেসের তালিকা মুদ্রণ করা যাক।

for (let classInterface of MyClass.getClass().implements) {
    console.log('Implemented interface: ' + classInterface.name)
}

রিফ্লেক-টিএস সহ সংকলন করুন এবং এটি চালু করুন:

$ node main.js
Implemented interface: MyInterface
Member name: counter - member kind: number
Member name: doSomething - member kind: function

Interfaceমেটা-টাইপের বিশদগুলির জন্য প্রতিবিম্ব.ড.টি .

আপডেট: আপনি এখানে একটি পূর্ণ কাজের উদাহরণ খুঁজে পেতে পারেন


8
ডাউনভোটেড কোস আমি ভেবেছিলাম এটি বোকা, তবে তারপরে এক মুহূর্তের জন্য বিরতি দেওয়া হয়েছিল, আপনার গিথুব পৃষ্ঠার দিকে তাকিয়ে দেখেছি এটি আপ টু ডেট রাখা হয়েছে এবং এর পরিবর্তে ভালভাবে নথিভুক্ত করা হয়েছে :-) আমি এখনও ঠিক এটির জন্য নিজেকে সঠিকভাবে প্রমাণ করতে পারি না implementsতবে আপনার প্রতিশ্রুতিটি স্বীকৃতি পেতে চেয়েছিলেন এবং তার অর্থ হতে
চাননি

5
প্রকৃতপক্ষে, আমি এই প্রতিচ্ছবি বৈশিষ্ট্যগুলির মূল লক্ষ্যটি দেখছি যা জাভা বিশ্ব ইতিমধ্যে দীর্ঘকাল ধরে রয়েছে এর মতো আরও ভাল আইওসি ফ্রেমওয়ার্ক তৈরি করা (স্প্রিং প্রথম এবং সবচেয়ে গুরুত্বপূর্ণ একটি) one আমি দৃ firm়ভাবে বিশ্বাস করি যে টাইপস্ক্রিপ্ট ভবিষ্যতের অন্যতম সেরা বিকাশের সরঞ্জাম হয়ে উঠতে পারে এবং প্রতিচ্ছবি এটির অন্যতম বৈশিষ্ট্য যা এটি সত্যই প্রয়োজন।
pcan

5
... আহ, তো কী, আমাদের এই সংকলক "বর্ধিতকরণগুলি" ভবিষ্যতের কোনও টাইপস্ক্রিপ্টে রোল করতে হবে? এটি কার্যকরভাবে টাইপস্ক্রিপ্টের কাঁটাচামচ, টাইপসক্রিপ্ট নিজেই নয়, তাই না? যদি তা হয় তবে এটি কোনও সম্ভাব্য দীর্ঘমেয়াদী সমাধান নয়।
দুদেওয়াদ

1
@ দেউদওয়াদ অন্যান্য অনেক বিষয়ে যেমন বলেছেন, এটি একটি অস্থায়ী সমাধান। আমরা ট্রান্সফর্মারগুলির মাধ্যমে সংকলক এক্সটেনসিবিলিটির জন্য অপেক্ষা করছি। অফিসিয়াল টাইপস্ক্রিপ্ট রেপোতে দয়া করে সম্পর্কিত সমস্যাগুলি দেখুন। তদুপরি, সমস্ত ব্যাপকভাবে গৃহীত শক্তিশালী-টাইপযুক্ত ভাষার প্রতিবিম্ব রয়েছে এবং আমি মনে করি টাইপস্ক্রিপ্টেরও এটি হওয়া উচিত। এবং আমার মতো আরও অনেক ব্যবহারকারীও তাই মনে করেন।
প্যাকান 21

হ্যাঁ এটি এমন নয় যে আমি রাজি নই - আমি এটিও চাই। কেবলমাত্র একটি কাস্টম সংকলক ঘুরছে ... তার মানে কি টাইপস্ক্রিপ্টের পরবর্তী প্যাচটি পোর্ট করা দরকার? আপনি যদি এটি পালন করছেন তবে কুডোস। অনেকটা কাজের মতো মনে হচ্ছে। এটি নক না।
dudewad


8

এখানে অন্য বিকল্প রয়েছে: মডিউল টিএস-ইন্টারফেস-বিল্ডার একটি বিল্ড-টাইম সরঞ্জাম সরবরাহ করে যা টাইপস্ক্রিপ্ট ইন্টারফেসকে একটি রানটাইম বর্ণনাকারীতে রূপান্তর করে, এবং টিএস-ইন্টারফেস-পরীক্ষক কোনও বস্তু এটি সন্তুষ্ট করে কিনা তা পরীক্ষা করতে পারে।

ওপির উদাহরণের জন্য,

interface A {
  member: string;
}

আপনি প্রথমে দৌড়াবেন ts-interface-builderযা বর্ণনাকারীর সাহায্যে একটি নতুন সংক্ষিপ্ত ফাইল তৈরি করবে, বলুন foo-ti.ts, যা আপনি এটির মতো ব্যবহার করতে পারেন:

import fooDesc from './foo-ti.ts';
import {createCheckers} from "ts-interface-checker";
const {A} = createCheckers(fooDesc);

A.check({member: "hello"});           // OK
A.check({member: 17});                // Fails with ".member is not a string" 

আপনি ওয়ান-লাইনার টাইপ-গার্ড ফাংশন তৈরি করতে পারেন:

function isA(value: any): value is A { return A.test(value); }

6

আমি উল্লেখ করতে চাই যে টাইপস্ক্রিপ্ট কোনও বস্তু একটি নির্দিষ্ট ইন্টারফেস প্রয়োগ করে কিনা তা গতিশীলভাবে পরীক্ষা করার জন্য সরাসরি প্রক্রিয়া সরবরাহ করে না।

পরিবর্তে, টাইপস্ক্রিপ্ট কোড জাভাস্ক্রিপ্ট কৌশলটি সদস্যের একটি উপযুক্ত সেট বস্তুটিতে উপস্থিত রয়েছে কিনা তা যাচাই করার জন্য ব্যবহার করতে পারে। উদাহরণ স্বরূপ:

var obj : any = new Foo();

if (obj.someInterfaceMethod) {
    ...
}

4
আপনার যদি জটিল আকার থাকে? আপনি প্রতিটি স্তরের গভীরতার প্রতিটি সম্পত্তি হার্ডকোড করতে চান না
টম

@ টম আমি অনুমান করি যে আপনি (চেকার ফাংশনের দ্বিতীয় প্যারামিটার হিসাবে) একটি রান-টাইম মান বা উদাহরণ / উদাহরণস্বরূপ - যেমন আপনি চান ইন্টারফেসের একটি অবজেক্ট। তারপরে, হার্ড-কোডিং কোডের পরিবর্তে, আপনি যে ইন্টারফেসটি চান তার কোনও উদাহরণ লিখুন ... এবং for (element in obj) {}দুটি বস্তুতে একই ধরণের অনুরূপ উপাদান রয়েছে কিনা তা যাচাই করতে কিছু ওয়ান-টাইম অবজেক্ট-তুলনা কোড লিখুন (উদাহরণস্বরূপ )।
ক্রিসডাব্লু

5

TypeGuards

interface MyInterfaced {
    x: number
}

function isMyInterfaced(arg: any): arg is MyInterfaced {
    return arg.x !== undefined;
}

if (isMyInterfaced(obj)) {
    (obj as MyInterfaced ).x;
}

2
"আরগটি মাইআইনটারফেসড" একটি আকর্ষণীয় টীকা। ব্যর্থ হলে কী হয়? একটি সংকলন টাইম ইন্টারফেস চেক দেখে মনে হচ্ছে - যা আমি প্রথম স্থানে চেয়েছিলাম। তবে যদি সংকলকটি প্যারামিটারগুলি পরীক্ষা করে তবে কেন কোনও ফাংশন বডি থাকে। এবং যদি এই জাতীয় চেক করা সম্ভব হয় তবে কেন এটিকে আলাদা ফাংশনে স্থানান্তরিত করুন।
lhk

1
@lhk শুধু টাইপ রক্ষীদের সম্পর্কে টাইপ করা বিষয় ডকুমেন্টেশন পড়া ... typescriptlang.org/docs/handbook/advanced-types.html
দিমিত্রি Matveev

3

ফেনটনের উত্তরের ভিত্তিতে , কোনও প্রদত্ত objectকীগুলি interfaceসম্পূর্ণ বা আংশিকভাবে রয়েছে কিনা তা যাচাই করতে এখানে আমার একটি ফাংশন বাস্তবায়ন করা হয়েছে ।

আপনার ব্যবহারের ক্ষেত্রে উপর নির্ভর করে আপনার ইন্টারফেসের প্রতিটি বৈশিষ্ট্যের প্রকার পরীক্ষা করতে হবে। নীচের কোডটি এটি করে না।

function implementsTKeys<T>(obj: any, keys: (keyof T)[]): obj is T {
    if (!obj || !Array.isArray(keys)) {
        return false;
    }

    const implementKeys = keys.reduce((impl, key) => impl && key in obj, true);

    return implementKeys;
}

ব্যবহারের উদাহরণ:

interface A {
    propOfA: string;
    methodOfA: Function;
}

let objectA: any = { propOfA: '' };

// Check if objectA partially implements A
let implementsA = implementsTKeys<A>(objectA, ['propOfA']);

console.log(implementsA); // true

objectA.methodOfA = () => true;

// Check if objectA fully implements A
implementsA = implementsTKeys<A>(objectA, ['propOfA', 'methodOfA']);

console.log(implementsA); // true

objectA = {};

// Check again if objectA fully implements A
implementsA = implementsTKeys<A>(objectA, ['propOfA', 'methodOfA']);

console.log(implementsA); // false, as objectA now is an empty object

2
export interface ConfSteps {
    group: string;
    key: string;
    steps: string[];
}
private verify(): void {
    const obj = `{
      "group": "group",
      "key": "key",
      "steps": [],
      "stepsPlus": []
    } `;
    if (this.implementsObject<ConfSteps>(obj, ['group', 'key', 'steps'])) {
      console.log(`Implements ConfSteps: ${obj}`);
    }
  }
private objProperties: Array<string> = [];

private implementsObject<T>(obj: any, keys: (keyof T)[]): boolean {
    JSON.parse(JSON.stringify(obj), (key, value) => {
      this.objProperties.push(key);
    });
    for (const key of keys) {
      if (!this.objProperties.includes(key.toString())) {
        return false;
      }
    }
    this.objProperties = null;
    return true;
  }

1
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কেন এবং / অথবা এই কোডটির প্রশ্নের উত্তর কীভাবে তার দীর্ঘমেয়াদী মানকে উন্নত করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করে।
xiawi

0

টাইপটি রান-টাইমে অজানা বলে আমি অজানা বিষয়টির সাথে তুলনা করতে কোডটি নীচে লিখেছি, কোনও প্রকারের বিরুদ্ধে নয়, তবে পরিচিত টাইপের কোনও বস্তুর বিরুদ্ধে:

  1. সঠিক ধরণের একটি নমুনা অবজেক্ট তৈরি করুন
  2. এর কোন উপাদানটি areচ্ছিক তা উল্লেখ করুন ify
  3. এই নমুনা বস্তুর বিরুদ্ধে আপনার অজানা বস্তুর গভীর তুলনা করুন

গভীর তুলনা করার জন্য আমি এখানে (ইন্টারফেস-অজোনস্টিক) কোডটি ব্যবহার করি:

function assertTypeT<T>(loaded: any, wanted: T, optional?: Set<string>): T {
  // this is called recursively to compare each element
  function assertType(found: any, wanted: any, keyNames?: string): void {
    if (typeof wanted !== typeof found) {
      throw new Error(`assertType expected ${typeof wanted} but found ${typeof found}`);
    }
    switch (typeof wanted) {
      case "boolean":
      case "number":
      case "string":
        return; // primitive value type -- done checking
      case "object":
        break; // more to check
      case "undefined":
      case "symbol":
      case "function":
      default:
        throw new Error(`assertType does not support ${typeof wanted}`);
    }
    if (Array.isArray(wanted)) {
      if (!Array.isArray(found)) {
        throw new Error(`assertType expected an array but found ${found}`);
      }
      if (wanted.length === 1) {
        // assume we want a homogenous array with all elements the same type
        for (const element of found) {
          assertType(element, wanted[0]);
        }
      } else {
        // assume we want a tuple
        if (found.length !== wanted.length) {
          throw new Error(
            `assertType expected tuple length ${wanted.length} found ${found.length}`);
        }
        for (let i = 0; i < wanted.length; ++i) {
          assertType(found[i], wanted[i]);
        }
      }
      return;
    }
    for (const key in wanted) {
      const expectedKey = keyNames ? keyNames + "." + key : key;
      if (typeof found[key] === 'undefined') {
        if (!optional || !optional.has(expectedKey)) {
          throw new Error(`assertType expected key ${expectedKey}`);
        }
      } else {
        assertType(found[key], wanted[key], expectedKey);
      }
    }
  }

  assertType(loaded, wanted);
  return loaded as T;
}

নীচে আমি এটি কীভাবে ব্যবহার করি তার একটি উদাহরণ দেওয়া আছে।

এই উদাহরণে আমি প্রত্যাশা করি যে জেএসএনে টিপলসের একটি অ্যারে রয়েছে, যার মধ্যে দ্বিতীয় উপাদানটি একটি ইন্টারফেসের উদাহরণ হিসাবে পরিচিত হয় User(যার দুটি বিকল্প উপাদান রয়েছে)।

টাইপস্ক্রিপ্টের টাইপ-চেকিংটি আমার স্যাম্পল অবজেক্টটি সঠিক কিনা তা নিশ্চিত করবে, তারপরে assertTypeT ফাংশনটি অজানা (জেএসএন থেকে লোড করা) বস্তুটি নমুনা বস্তুর সাথে মেলে কিনা তা পরীক্ষা করে।

export function loadUsers(): Map<number, User> {
  const found = require("./users.json");
  const sample: [number, User] = [
    49942,
    {
      "name": "ChrisW",
      "email": "example@example.com",
      "gravatarHash": "75bfdecf63c3495489123fe9c0b833e1",
      "profile": {
        "location": "Normandy",
        "aboutMe": "I wrote this!\n\nFurther details are to be supplied ..."
      },
      "favourites": []
    }
  ];
  const optional: Set<string> = new Set<string>(["profile.aboutMe", "profile.location"]);
  const loaded: [number, User][] = assertTypeT(found, [sample], optional);
  return new Map<number, User>(loaded);
}

আপনি কোনও ব্যবহারকারী-সংজ্ঞায়িত টাইপ গার্ড প্রয়োগের ক্ষেত্রে এই জাতীয় একটি চেক অনুরোধ করতে পারেন।


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