टाइपस्क्रिप्ट में इंटरफ़ेस के लिए कास्ट ऑब्जेक्ट


101

मैं अपने कोड में एक्सप्रेस (बॉडी-पार्सर मिडलवेयर का उपयोग करके) एक इंटरफेस के लिए अपने कोड से एक कास्ट करने की कोशिश कर रहा हूं, लेकिन यह प्रकार की सुरक्षा को लागू नहीं कर रहा है।

यह मेरा इंटरफ़ेस है:

export interface IToDoDto {
  description: string;
  status: boolean;
};

यह वह कोड है जहां मैं कलाकारों को करने की कोशिश कर रहा हूं:

@Post()
addToDo(@Response() res, @Request() req) {
  const toDo: IToDoDto = <IToDoDto> req.body; // <<< cast here
  this.toDoService.addToDo(toDo);
  return res.status(HttpStatus.CREATED).end();
}

और अंत में, सेवा पद्धति जिसे कहा जा रहा है:

public addToDo(toDo: IToDoDto): void {
  toDo.id = this.idCounter;
  this.todos.push(toDo);
  this.idCounter++;
}

मैं जो भी दलीलें पास कर सकता हूं, यहां तक ​​कि जो इंटरफ़ेस की परिभाषा के मिलान के करीब नहीं आते हैं , और यह कोड ठीक काम करेगा। मुझे उम्मीद है, अगर रिस्पांस बॉडी से इंटरफ़ेस तक का कास्ट संभव नहीं है, तो यह अपवाद है कि जावा या सी # जैसे रनटाइम पर फेंक दिया जाएगा।

मैंने पढ़ा है कि टाइपस्क्रिप्ट में कास्टिंग मौजूद नहीं है, केवल टाइप अभिकथन है, इसलिए यह केवल कंपाइलर को बताएगा कि कोई ऑब्जेक्ट टाइप का है x, इसलिए ... क्या मैं गलत हूं? प्रकार सुरक्षा को लागू करने और सुनिश्चित करने का सही तरीका क्या है?


1
कृपया "यह काम नहीं कर रहा है" को परिभाषित करें। सटीक होना। क्या कोई त्रुटि है? कौनसा? संकलन-समय पर? चलने के समय पर? क्या होता है?
जेबी निजेट

1
रनटाइम के दौरान, कोड सामान्य रूप से निष्पादित होता है, जो भी वस्तु मैं पास करता हूं।
इलायस गार्सिया

यह स्पष्ट नहीं है कि आप क्या पूछ रहे हैं
निट्ज़ेन तोमर

मेरा सवाल है कि टाइप की गई वस्तु पर आने वाली वस्तु को कैसे डाला जाए। यदि कास्ट संभव नहीं है, तो रनटाइम पर एक अपवाद फेंकें, जैसे जावा, सी # ...
एलियास गार्सिया

जवाबों:


143

जावास्क्रिप्ट में कोई कास्टिंग नहीं है, इसलिए आप फेंक नहीं सकते यदि "कास्टिंग विफल रहता है"।
टाइपस्क्रिप्ट कास्टिंग का समर्थन करता है, लेकिन यह केवल संकलन समय के लिए है, और आप इसे इस तरह से कर सकते हैं:

const toDo = <IToDoDto> req.body;
// or
const toDo = req.body as IToDoDto;

यदि मान मान्य है और यदि कोई त्रुटि नहीं है, तो आप रनटाइम पर जांच कर सकते हैं:

function isToDoDto(obj: any): obj is IToDoDto {
    return typeof obj.description === "string" && typeof obj.status === "boolean";
}

@Post()
addToDo(@Response() res, @Request() req) {
    if (!isToDoDto(req.body)) {
        throw new Error("invalid request");
    }

    const toDo = req.body as IToDoDto;
    this.toDoService.addToDo(toDo);
    return res.status(HttpStatus.CREATED).end();
}

संपादित करें

जैसा कि @huyz ने बताया, टाइप के लिए कोई आवश्यकता नहीं है क्योंकि isToDoDtoएक प्रकार का गार्ड है, इसलिए यह पर्याप्त होना चाहिए:

if (!isToDoDto(req.body)) {
    throw new Error("invalid request");
}

this.toDoService.addToDo(req.body);

मुझे नहीं लगता कि const toDo = req.body as IToDoDto;टीएस संकलक को पता है कि यह IToDoDtoइस बिंदु पर है क्योंकि आपको कास्ट की आवश्यकता है
huyz

10
सामान्य रूप से टाइपिंग की तलाश में किसी के लिए भी, <> का उपयोग न करें। यह पदावनत है। उपयोगas
अभिषेक देब

" जावास्क्रिप्ट में कोई कास्टिंग नहीं है, इसलिए आप फेंक नहीं सकते यदि" कास्टिंग विफल रहता है "। मुझे लगता है, बिंदु से अधिक, टाइपस्क्रिप्ट में इंटरफेस कार्रवाई योग्य नहीं हैं; वास्तव में, वे 100% सिंथेटिक चीनी हैं । वे संरचनाओं को अवधारणात्मक रूप से बनाए रखना आसान बनाते हैं , लेकिन ट्रांसप्लड कोड पर कोई वास्तविक प्रभाव नहीं है - जो कि ओपी के प्रश्न साक्ष्य के रूप में, imo, पागलपनपूर्ण भ्रमित / विरोधी पैटर्न है। कोई कारण नहीं है कि इंटरफेस मैच के लिए असफल ट्रांसप्लड जावास्क्रिप्ट में फेंक नहीं सकता है; यह टाइपस्क्रिप्ट द्वारा एक सचेत (और खराब, imo) विकल्प है।
रफिन

@ इरफ़िन इंटरफेस सिंटैक्टिक शुगर नहीं है, लेकिन उन्होंने इसे केवल रनटाइम में रखने के लिए एक जागरूक विकल्प बनाया। मुझे लगता है कि यह एक शानदार विकल्प है, इस तरह रनटाइम में कोई प्रदर्शन जुर्माना नहीं है।
निट्ज्जन तोमर

तोमायो टॉमहोटो ? टाइपस्क्रिप्ट में इंटरफ़ेस से टाइप सुरक्षा आपके ट्रांसप्लड कोड तक नहीं होती है, और यहां तक ​​कि प्री-रनटाइम प्रकार की सुरक्षा गंभीर रूप से सीमित है - जैसा कि हम ओपी के मुद्दे में देखते हैं जहां कोई प्रकार की सुरक्षा नहीं है । टीएस कह सकता है, "अरे, रुको, तुम्हारी anyगारंटी IToDoDtoअभी तक नहीं है!", लेकिन टीएस ने नहीं चुना। यदि कंपाइलर केवल कुछ प्रकार के संघर्षों को पकड़ता है , और कोई भी ट्रांसप्लड कोड में नहीं है (और आप सही हैं, तो मुझे अधिक स्पष्ट @ होना चाहिए कि मूल में), इंटरफेस दुर्भाग्य से, imo, [ज्यादातर?] चीनी हैं।
Ruffin

7

असंगत प्रकारों और इंटरफेस के बीच भी टाइप-कास्ट को मजबूर करने का एक और तरीका है जहां टीएस कंपाइलर सामान्य रूप से शिकायत करता है:

export function forceCast<T>(input: any): T {

  // ... do runtime checks here

  // @ts-ignore <-- forces TS compiler to compile this as-is
  return input;
}

फिर आप इसका उपयोग कास्ट ऑब्जेक्ट्स को एक निश्चित प्रकार के लिए मजबूर करने के लिए कर सकते हैं:

import { forceCast } from './forceCast';

const randomObject: any = {};
const typedObject = forceCast<IToDoDto>(randomObject);

ध्यान दें कि मैंने उस हिस्से को छोड़ दिया है जिसे आप जटिलता को कम करने के लिए कास्टिंग से पहले रनटाइम चेक करने वाले हैं। मैं अपनी परियोजना में क्या कर रहा हूँ .d.tsJSON स्कीमा में अपने सभी इंटरफ़ेस फ़ाइलों को संकलित कर रहा ajvहै और रनटाइम में मान्य करने के लिए उपयोग कर रहा है।


2

यदि यह किसी की मदद करता है, तो मुझे एक मुद्दा मिल रहा था जहां मैं एक समान इंटरफ़ेस के साथ किसी अन्य प्रकार के रूप में एक वस्तु का इलाज करना चाहता था। मैंने निम्नलिखित प्रयास किया:

लाइनिंग पास नहीं किया

const x = new Obj(a as b);

लिंटर शिकायत कर रहा aथा कि लापता गुण मौजूद थे b। दूसरे शब्दों में, aकुछ गुण और तरीके थे b, लेकिन सभी नहीं। इसके आसपास काम करने के लिए, मैंने वीएस कोड के सुझाव का पालन किया:

लाइनिंग और परीक्षण पास किया

const x = new Obj(a as unknown as b);

ध्यान दें कि यदि आपका कोड उस प्रकार के गुणों में से एक को कॉल करने का प्रयास करता है जो टाइप bपर लागू नहीं है a, तो आपको रनटाइम फॉल्ट का एहसास होना चाहिए।


1
मुझे खुशी है कि मुझे यह उत्तर मिला, लेकिन ध्यान दें कि यदि आप नेटवर्क पर या किसी अन्य ऐप पर 'x' भेज रहे हैं, तो आप व्यक्तिगत जानकारी लीक कर सकते हैं (यदि 'a' उदाहरण के लिए उपयोगकर्ता है), क्योंकि 'x' अभी भी है 'a' के सभी गुण हैं, वे केवल टाइपस्क्रिप्ट के लिए अनुपलब्ध हैं।
ज़ोल्टन मटुक

@ ZoltánMatók अच्छी बात है। इसके अलावा, नेटवर्क पर क्रमबद्ध ऑब्जेक्ट भेजने के बारे में जावा स्टाइल गेटर्स के लिए एक तर्क है और जावास्क्रिप्ट getऔर setविधियों पर बसता है ।
जेसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.