টাইপস্ক্রিপ্টে পরামিতি হিসাবে শক্তভাবে টাইপড ফাংশনগুলি কি সম্ভব?


558

টাইপস্ক্রিপ্টে, আমি কোনও ফাংশনের একটি প্যারামিটারকে টাইপ ফাংশন হিসাবে ঘোষণা করতে পারি। আমি কি অনুপস্থিত তা করার কোনও "টাইপ-নিরাপদ" উপায় আছে? উদাহরণস্বরূপ, এটি বিবেচনা করুন:

class Foo {
    save(callback: Function) : void {
        //Do the save
        var result : number = 42; //We get a number from the save operation
        //Can I at compile-time ensure the callback accepts a single parameter of type number somehow?
        callback(result);
    }
}

var foo = new Foo();
var callback = (result: string) : void => {
    alert(result);
}
foo.save(callback);

সেভ কলব্যাক নিরাপদ টাইপ নয়, আমি এটিকে কলব্যাক ফাংশন দিচ্ছি যেখানে ফাংশনের প্যারামিটারটি একটি স্ট্রিং তবে আমি এটিকে একটি নম্বর দিয়ে যাচ্ছি এবং কোনও ত্রুটি ছাড়াই সংকলন করছি। আমি কি টাইপ-সেফ ফাংশনটি সেভ করতে ফলাফলের প্যারামিটার তৈরি করতে পারি?

টিএল; ডিআর সংস্করণ: টাইপস্ক্রিপ্টে কোনও নেট ডেলিগেটের সমতুল্য?

উত্তর:


802

অবশ্যই। একটি ফাংশনের ধরণটিতে তার আর্গুমেন্টের প্রকার এবং তার ফেরতের প্রকার থাকে। এখানে আমরা উল্লেখ করেছি যে callbackপ্যারামিটারের ধরণটি অবশ্যই "ফাংশন যা কোনও নম্বর গ্রহণ করে এবং প্রকার ফেরতের প্রকার any" হতে হবে:

class Foo {
    save(callback: (n: number) => any) : void {
        callback(42);
    }
}
var foo = new Foo();

var strCallback = (result: string) : void => {
    alert(result);
}
var numCallback = (result: number) : void => {
    alert(result.toString());
}

foo.save(strCallback); // not OK
foo.save(numCallback); // OK

আপনি যদি চান, আপনি এটি সজ্জিত করতে কোনও প্রকারের নাম নির্ধারণ করতে পারেন :

type NumberCallback = (n: number) => any;

class Foo {
    // Equivalent
    save(callback: NumberCallback) : void {
        callback(42);
    }
}

6
(n: number) => anyমানে কোন ফাংশনের স্বাক্ষর?
নিক্ক ওয়াং

16
@ নিক্কওয়ং এর অর্থ হ'ল ফাংশনটি একটি প্যারামিটার নেয় (ক number) তবে রিটার্নের ধরণটি মোটেই সীমাবদ্ধ নয় (কোনও মান বা এমনকি হতে পারে void)
ড্যানিয়েল আরউইকার

16
nএই বাক্যবিন্যাসের বিন্দুটি কী ? একা ইনপুট এবং আউটপুট ধরণের কি যথেষ্ট হবে না?
ইউহুয়ান জিয়াং

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

3
@ ইউহুয়ান জিয়াং এই পোস্টটি আপনার আগ্রহী হতে পারে
ওফিডিয়ান

93

এখানে কিছু সাধারণ .NET প্রতিনিধিদের টাইপস্ক্রিপ্ট সমতুল্য:

interface Action<T>
{
    (item: T): void;
}

interface Func<T,TResult>
{
    (item: T): TResult;
}

2
সম্ভবত দেখতে দরকারী কিন্তু আসলে এই জাতীয় ধরণগুলি ব্যবহার করা এটি একটি অ্যান্টি-প্যাটার্ন হবে। যাইহোক সেগুলি সি # প্রতিনিধিদের চেয়ে জাভা এসএএম টাইপের মতো দেখতে বেশি লাগে। অবশ্যই তারা নেই এবং এগুলি টাইপ ওরফে ফর্মের সমতুল্য যা ফাংশনগুলির জন্য আরও মার্জিত
আলুয়ান হাদাদ

5
@ অ্যালুয়ানহাদদাদ আপনি কেন এটিকে বিরোধী ধাঁচের ভাবেন?
ম্যাক্স আর ম্যাককার্টি

8
কারণটি হ'ল টাইপস্ক্রিপ্টের একটি সংক্ষিপ্ত ফাংশন টাইপের আক্ষরিক সিনট্যাক্স রয়েছে যা এই জাতীয় ইন্টারফেসের প্রয়োজনীয়তা বাধা দেয়। সি # তে প্রতিনিধিরা নামমাত্র, তবে প্রতিনিধি Actionএবং Funcউভয়ই উভয়ই নির্দিষ্ট প্রতিনিধি প্রকারের বেশিরভাগ প্রয়োজনীয়তা বজায় রাখেন এবং মজার বিষয় হল কাঠামোগত টাইপিংয়ের লক্ষণকে সি # এ দিন। এই প্রতিনিধিদের নেতিবাচক দিকটি হ'ল তাদের নামগুলি কোনও অর্থ দেয় না তবে অন্যান্য সুবিধাগুলি সাধারণত এটির চেয়ে বেশি। টাইপস্ক্রিপ্টে আমাদের কেবল এই ধরণের প্রয়োজন হয় না। সুতরাং অ্যান্টি-প্যাটার্ন হবে function map<T, U>(xs: T[], f: Func<T, U>)। পছন্দfunction map<T, U>(xs: T[], f: (x: T) => U)
আলুয়ান হাদাদ

6
এটি স্বাদের বিষয়, কারণ এগুলি এমন একটি ভাষার সমতুল রূপ যা রান টাইম ধরণের নয়। আজকাল আপনি ইন্টারফেসের পরিবর্তে টাইপ অ্যালিয়াসও ব্যবহার করতে পারেন।
ড্রউ নোকস

18

আমি বুঝতে পারি যে এই পোস্টটি পুরানো, তবে আরও একটি কমপ্যাক্ট পদ্ধতির যা জিজ্ঞাসা করা হয়েছিল তার চেয়ে কিছুটা আলাদা, তবে এটি একটি সহায়ক সহায়ক হতে পারে। আপনি মূলত যখন পদ্ধতি (কলিং ইন-লাইন ফাংশন ডিক্লেয়ার করতে পারেন Fooএর save()এই ক্ষেত্রে)। এটি দেখতে এমন কিছু লাগবে:

class Foo {
    save(callback: (n: number) => any) : void {
        callback(42)
    }

    multipleCallbacks(firstCallback: (s: string) => void, secondCallback: (b: boolean) => boolean): void {
        firstCallback("hello world")

        let result: boolean = secondCallback(true)
        console.log("Resulting boolean: " + result)
    }
}

var foo = new Foo()

// Single callback example.
// Just like with @RyanCavanaugh's approach, ensure the parameter(s) and return
// types match the declared types above in the `save()` method definition.
foo.save((newNumber: number) => {
    console.log("Some number: " + newNumber)

    // This is optional, since "any" is the declared return type.
    return newNumber
})

// Multiple callbacks example.
// Each call is on a separate line for clarity.
// Note that `firstCallback()` has a void return type, while the second is boolean.
foo.multipleCallbacks(
    (s: string) => {
         console.log("Some string: " + s)
    },
    (b: boolean) => {
        console.log("Some boolean: " + b)
        let result = b && false

        return result
    }
)

multipleCallback()পদ্ধতির নেটওয়ার্ক কল সফল বা ব্যর্থ হতে পারে মতো জিনিসগুলির জন্য খুবই দরকারী। আবার ধরে নেওয়া একটি নেটওয়ার্ক কল উদাহরণ হিসাবে, যখন multipleCallbacks()বলা হয়, সাফল্য এবং ব্যর্থতা উভয়ের জন্য আচরণকে একটি স্পটে সংজ্ঞায়িত করা যায় যা ভবিষ্যতের কোড পাঠকদের জন্য আরও বেশি স্পষ্টতার জন্য leণ দেয়।

সাধারণত, আমার অভিজ্ঞতায়, এই পদ্ধতির নিজেকে সামগ্রিকভাবে আরও সংক্ষিপ্ত, কম বিশৃঙ্খলা এবং বৃহত্তর স্পষ্টতা হিসাবে ধার দেয়।

সকলের সৌভাগ্য হোক!


16
type FunctionName = (n: inputType) => any;

class ClassName {
    save(callback: FunctionName) : void {
        callback(data);
    }
}

এটি অবশ্যই কার্যকরী প্রোগ্রামিং দৃষ্টান্তের সাথে একত্রিত হয়।


6
আপনি inputTypeবরং এটি কল করা returnTypeউচিত? কোথায় inputTypeধরনের হয় dataযা আপনাকে একটি প্যারামিটার পাস callbackফাংশন।
ক্রিসডাব্লু

হ্যাঁ @ ক্রিসডব্লু আপনি ঠিক বলেছেন, ইনপুটটাইপ আরও অর্থবোধ করে। ধন্যবাদ!
কৃষ্ণ গানেরিওয়াল

2

টিএস-তে আমরা নিম্নলিখিত রীতিগুলিতে ফাংশনগুলি টাইপ করতে পারি:

ফাংশনের ধরণ / স্বাক্ষর

এটি নিম্নলিখিত ক্রিয়াকলাপগুলি / কার্যাদি বাস্তবায়নের জন্য ব্যবহৃত হয়:

(arg1: Arg1type, arg2: Arg2type) : ReturnType

উদাহরণ:

function add(x: number, y: number): number {
    return x + y;
}

class Date {
  setTime(time: number): number {
   // ...
  }

}

ফাংশন ধরণের লিটারাল

ফাংশন ধরণের আক্ষরিকতা কোনও ফাংশনের ধরণের ঘোষণার অন্য উপায়। এগুলি সাধারণত একটি উচ্চতর ক্রমের ফাংশনের স্বাক্ষরে প্রয়োগ করা হয়। একটি উচ্চতর ক্রম ফাংশন এমন একটি ফাংশন যা প্যারামিটার হিসাবে ফাংশন গ্রহণ করে বা যা কোনও ফাংশন দেয়। এটিতে নিম্নলিখিত বাক্য গঠন রয়েছে:

(arg1: Arg1type, arg2: Arg2type) => ReturnType

উদাহরণ:

type FunctionType1 = (x: string, y: number) => number;

class Foo {
    save(callback: (str: string) => void) {
       // ...
    }

    doStuff(callback: FunctionType1) {
       // ...
    }

}

1

আপনি যদি প্রথমে ফাংশন টাইপ সংজ্ঞায়িত করেন তবে এটির মতো দেখাবে

type Callback = (n: number) => void;

class Foo {
    save(callback: Callback) : void {        
        callback(42);
    }
}

var foo = new Foo();
var stringCallback = (result: string) : void => {
    console.log(result);
}

var numberCallback = (result: number) : void => {
    console.log(result);
}

foo.save(stringCallback); //--will be showing error
foo.save(numberCallback);

প্লেইন প্রপার্টি সিনট্যাক্স ব্যবহার করে ফাংশনের ধরণ ছাড়াই এটি হবে:

class Foo {
    save(callback: (n: number) => void) : void {        
        callback(42);
    }
}

var foo = new Foo();
var stringCallback = (result: string) : void => {
    console.log(result);
}

var numberCallback = (result: number) : void => {
    console.log(result);
}

foo.save(stringCallback); //--will be showing error
foo.save(numberCallback);

আপনি যদি সি # জেনেরিক প্রতিনিধিদের মতো কোনও ইন্টারফেস ফাংশন ব্যবহার করে চান তা হ'ল:

interface CallBackFunc<T, U>
{
    (input:T): U;
};

class Foo {
    save(callback: CallBackFunc<number,void>) : void {        
        callback(42);
    }
}

var foo = new Foo();
var stringCallback = (result: string) : void => {
    console.log(result);
}

var numberCallback = (result: number) : void => {
    console.log(result);
}

let strCBObj:CallBackFunc<string,void> = stringCallback;
let numberCBObj:CallBackFunc<number,void> = numberCallback;

foo.save(strCBObj); //--will be showing error
foo.save(numberCBObj);

0

অন্যরা যা বলেছে তা ছাড়াও, একটি সাধারণ সমস্যা হ'ল ওভারলোড হওয়া একই ফাংশনের প্রকারগুলি ঘোষণা করা। টিপিক্যাল কেস হল ইভেন্টইমিটার অন () পদ্ধতি যা একাধিক ধরণের শ্রোতাকে গ্রহণ করবে। রিডুএক্স ক্রিয়াগুলির সাথে কাজ করার সময় একই ঘটনা ঘটতে পারে - এবং সেখানে ওভারলোডিং চিহ্নিত করার জন্য আপনি অ্যাকশন টাইপটিকে আক্ষরিক হিসাবে ব্যবহার করেন ইভেন্ট ইভেন্টটার ক্ষেত্রে আপনি ইভেন্টের নাম আক্ষরিক প্রকারটি ব্যবহার করেন:

interface MyEmitter extends EventEmitter {
  on(name:'click', l: ClickListener):void
  on(name:'move', l: MoveListener):void
  on(name:'die', l: DieListener):void
  //and a generic one
  on(name:string, l:(...a:any[])=>any):void
}

type ClickListener = (e:ClickEvent)=>void
type MoveListener = (e:MoveEvent)=>void
... etc

// will type check the correct listener when writing something like:
myEmitter.on('click', e=>...<--- autocompletion
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.