সংজ্ঞা ফাইলে আমদানি ক্লাস (* d.ts)


96

সেশন স্টোরেজে আমার কাস্টম ডেটা ব্যবহারের অনুমতি দেওয়ার জন্য আমি এক্সপ্রেস সেশন টাইপগুলি প্রসারিত করতে চাই। আমার একটি বিষয় আছে req.session.userযা আমার শ্রেণীর উদাহরণ User:

export class User {
    public login: string;
    public hashedPassword: string;

    constructor(login?: string, password?: string) {
        this.login = login || "" ;
        this.hashedPassword = password ? UserHelper.hashPassword(password) : "";
    }
}

সুতরাং আমি own.d.tsবিদ্যমান এক্সপ্রেস সেশন টাইপিংয়ের সাথে সংজ্ঞা সংহত করতে আমার ফাইল তৈরি করেছি :

import { User } from "./models/user";

declare module Express {
    export interface Session {
        user: User;
    }
}

তবে এটি মোটেও কাজ করছে না - ভিএস কোড এবং টিএসসি এটি দেখতে পাবে না। সুতরাং আমি পরীক্ষার সংজ্ঞাটি সাধারণ ধরণের দিয়ে তৈরি করেছি:

declare module Express {
    export interface Session {
        test: string;
    }
}

এবং পরীক্ষার ক্ষেত্র ঠিকঠাক কাজ করছে, তাই আমদানির কারণ সমস্যা।

আমি /// <reference path='models/user.ts'/>পরিবর্তে আমদানি করার চেষ্টা করেছি কিন্তু টিএসসি ব্যবহারকারীর ক্লাসটি দেখেনি - আমি কীভাবে * d.ts ফাইলটিতে নিজের ক্লাসটি ব্যবহার করতে পারি?

সম্পাদনা: সংকলনে সংজ্ঞা ফাইল উত্পন্ন করতে আমি টিএসসি সেট করেছিলাম এবং এখন আমার ইউজার.ডি.এস.টি.

export declare class User {
    login: string;
    hashedPassword: string;
    constructor();
    constructor(login: string, password: string);
}

এবং এক্সপ্রেস সেসিয়ান বাড়ানোর জন্য নিজস্ব টাইপিং ফাইল:

import { User } from "./models/user";
declare module Express {
    export interface Session {
        user: User;
        uuid: string;
    }
}

শীর্ষে আমদানি বিবৃতি যখন এখনও কাজ করছে না। কোন ধারনা?

উত্তর:


271

দুই বছর টাইপস্ক্রিপ্ট বিকাশের পরে অবশেষে আমি এই সমস্যাটি সমাধান করতে সক্ষম হয়েছি।

মূলত, টাইপস্ক্রিপ্টের দুটি ধরণের মডিউল প্রকারের ঘোষণা রয়েছে: "স্থানীয়" (সাধারণ মডিউলগুলি) এবং পরিবেষ্টিত (বৈশ্বিক) দ্বিতীয় ধরণের বিশ্বব্যাপী মডিউল ঘোষণা লিখতে দেয় যা বিদ্যমান মডিউল ঘোষণার সাথে একত্রীকরণ করা হয়। এই ফাইলগুলির মধ্যে পার্থক্য কী?

d.tsফাইলগুলি কেবলমাত্র কোনও আমদানি না থাকলেই একটি পরিবেষ্টিত মডিউল ঘোষণা হিসাবে বিবেচিত হবে। আপনি যদি কোনও আমদানি লাইন সরবরাহ করেন তবে এখন এটি একটি সাধারণ মডিউল ফাইল হিসাবে ধরা হবে, বিশ্বব্যাপী নয়, সুতরাং মডিউলগুলির সংজ্ঞা বৃদ্ধি করে না।

সুতরাং আমরা এখানে যে সমস্ত সমাধান আলোচনা করেছি সেগুলি কাজ করে না। তবে সৌভাগ্যক্রমে, টিএস ২.৯ থেকে আমরা import()সিনট্যাক্স ব্যবহার করে বৈশ্বিক মডিউল ঘোষণায় প্রকারগুলি আমদানি করতে সক্ষম হয়েছি :

declare namespace Express {
  interface Request {
    user: import("./user").User;
  }
}

সুতরাং লাইনটি import("./user").User;যাদু করে এবং এখন সমস্ত কিছুই কাজ করে :)


4
এটি করার সঠিক উপায় এটি হ'ল কমপক্ষে সাম্প্রতিক সংস্করণগুলির সাথে টাইপস্ক্রিপ্ট
জেফারসন টাভারেস

4
নোডের processঅবজেক্টের মতো বৈশ্বিক মডিউলগুলি প্রসারিত ইন্টারফেসগুলি ঘোষণার সময় এই পদ্ধতির আদর্শ সমাধান ।
টিফেন এলিস

4
ধন্যবাদ, এক্সপ্রেস মিডলওয়্যার প্রসারিত করে আমার সমস্যাগুলি ঠিক করার একমাত্র স্পষ্ট উত্তর!
কাটসুক

থেক্স, অনেক সাহায্য করেছে। বিদ্যমান প্রকল্পে এটি করার অন্য কোনও উপায় ছিল না। অনুরোধ ক্লাস প্রসারিত করার চেয়ে এটিকে পছন্দ করুন। Dziękuję bardzo।
ক্রিস্টোফ গিয়ার্স

4
আপনাকে ধন্যবাদ @ মাইচা লাইটেক আমি ভাবছি এই পদ্ধতির জন্য কোনও অফিসিয়াল ডকুমেন্টেশন রেফারেন্স আছে কি?
জেনা

3

হালনাগাদ

টাইপস্ক্রিপ্ট ২.৯ যেহেতু, আপনি বৈশ্বিক মডিউলগুলিতে প্রকারগুলি আমদানি করতে সক্ষম বলে মনে হচ্ছে। আরও তথ্যের জন্য গৃহীত উত্তর দেখুন।

মূল উত্তর

আমি মনে করি আপনি যে সমস্যার মুখোমুখি হচ্ছেন সেটি হ'ল ক্লাস টাইপিংয়ের পরে মডিউল ঘোষণাগুলি বাড়ানো সম্পর্কে ।

রফতানিটি ঠিকঠাক, আপনি যদি এটি সংকলন করার চেষ্টা করেন তবে আপনি খেয়াল করবেন:

// app.ts  
import { User } from '../models/user'
let theUser = new User('theLogin', 'thePassword')

দেখে মনে হচ্ছে আপনি মডিউল ঘোষণাকে বাড়ানোর চেষ্টা করছেন Expressএবং আপনি সত্যিই কাছাকাছি রয়েছেন । এই কৌতুক করতে হবে:

// index.d.ts
import { User } from "./models/user";
declare module 'express' {
  interface Session {
    user: User;
    uuid: string;
  }
}

তবে এই কোডটির যথার্থতা অবশ্যই এক্সপ্রেস ডিক্লেয়ারেশন ফাইলের মূল বাস্তবায়নের উপর নির্ভর করে।


যদি আমি ইম্পোর্ট বিবৃতিটি সরাতে ভিতরে আমি ভুল পাবেন: Import declarations in a namespace cannot reference a module.। আমি আপনার কোড কপি পেস্ট-আমি যদি করেছেন: Import or export declaration in an ambient module declaration cannot reference module through relative module name.। এবং যদি আমি অপেক্ষাকৃত পাথ ব্যবহার করার চেষ্টা করি তবে আমি আমার ফাইলটি সনাক্ত করতে পারছি না, তাই আমি নোড_মডিউলগুলি অ্যাড পাথ যুক্ত করার জন্য ডিক্লেয়ারেশন ফোল্ডারটি স্থানান্তরিত করেছি "declarations/models/user"তবে এখনও পুরো ডি.টি.এস. কাজ করছে না - ইন্টিলেসেন্সে এক্সপ্রেস সেশনের নিজস্ব সম্প্রসারণ দেখতে পাচ্ছে না বা টিএসসি
মিশা লাইটেক

আমি এই ত্রুটিগুলির সাথে পরিচিত নই, দুঃখিত। আপনার সেটআপে কিছু আলাদা থাকতে পারে? এটি কি আপনার জন্য সংকলন করতে পারে? gist.github.com/pellejacobs/498c997ebb8679ea90826177cf8a9bad
পেলে জ্যাকবস

এইভাবে এটি কাজ করে কিন্তু এখনও বাস্তব অ্যাপে কাজ করে না। আমার সেশন অবজেক্টের সাথে একটি এক্সপ্রেস রিকোয়েস্ট অবজেক্ট রয়েছে এবং এটির অন্য ধরণের ঘোষিত আছে - নেমস্পেস এক্সপ্রেসে মডিউল 'এক্সপ্রেস' নয়: github.com/DefinitelyTypeed/DefinitelyTypeed/blob/master/…
Michał Lytek

4
এটি আমার পক্ষেও কাজ করে না। আমি একবার আমার tsd.d.ts ফাইলটিতে আমদানি বিবৃতি যুক্ত করলে পুরো ফাইলটি কাজ বন্ধ করে দেয়। (সেই ফাইলের মধ্যে সংজ্ঞায়িত জিনিসগুলির জন্য আমি আমার আবেদনের বাকি অংশগুলিতে ত্রুটি পেয়েছি))
ভার্ন জেনসেন

4
আমারও একই সমস্যা ছিল। আপনি যদি আপনার .d.ts এর মধ্যে একটি ঘোষিত মডিউলে আমদানি ব্যবহার করেন তবে এটি কাজ করে: declare module 'myModule' {import { FancyClass } from 'fancyModule'; export class MyClass extends FancyClass {} }
জুনার

2

মাইচা লাইটেকের উত্তরটির জন্য ধন্যবাদ । আমি আমার প্রকল্পে ব্যবহৃত অন্য পদ্ধতি এখানে।

আমরা এটিকে যে কোনও জায়গায় না লিখে একাধিকবার আমদানি Userপুনঃব্যবহার করতে পারি import("./user").User, এমনকি এটি প্রসারিত বা পুনরায় এক্সপোর্টও করতে পারি।

declare namespace Express {
  import("./user");  // Don't delete this line.
  import { User } from "./user";

  export interface Request {
    user: User;
    target: User;
    friend: User;
  }

  export class SuperUser extends User {
    superPower: string;
  }

  export { User as ExpressUser }
}

আনন্দ কর :)


-1

যুক্তি অনুসরণ করা কি কেবল সম্ভব নয় express-session:

own.d.ts:

import express = require('express');
import { User } from "../models/user";

declare global {
    namespace Express {
        interface Session {
            user: User;
            uuid: string;
        }
    }
}

মূল index.ts:

import express from 'express';
import session from 'express-session';
import own from './types/own';

const app = express();
app.get('/', (req, res) => {
    let username = req!.session!.user.login;
});

কমপক্ষে এটি কোনও সমস্যা ছাড়াই সংকলিত বলে মনে হচ্ছে। সম্পূর্ণ কোডের জন্য, https://github.com/masa67/so39040108 দেখুন


4
আপনাকে অবশ্যই ঘোষণা ফাইলগুলি আমদানি করতে হবে না, কারণ tscসেগুলি সংকলন করে না। সেগুলি সংকলনের মধ্যে থাকলেও আউটপুটে নয়
বালিন্ট সিসাক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.