Как сделать тип универсальным?

Ссылка скопирована
1 ответ

метод sendConfirmMail это отправка почты при регистрации, просто пример реализации, она принимает юзера с интерфейсом IEmailUser который должен передаваться в главный интерфейс IMail и расширять его

export interface IEmailUser {   email: string   name: string   phone: number }  async sendConfirmMail(user: IEmailUser) {     const mailContent:IMail<IEmailUser> = {       to: user.email,       subject: 'Confirm registration', //Example       template: 'confirmReg',       context: {         email: user.email,         name: user.name,         phone: user.phone       }     }     this.mailService.emailSend(mailContent)   }

export interface IEmailUser { email: string name: string phone: number } async sendConfirmMail(user: IEmailUser) { const mailContent:IMail<IEmailUser> = { to: user.email, subject: 'Confirm registration', //Example template: 'confirmReg', context: { email: user.email, name: user.name, phone: user.phone } } this.mailService.emailSend(mailContent) }

после чего уже в сервисе должен в методе emailSend переменная mailData должна иметь интерфейс уже расширеный IMail

export interface IMail<T> {   to: string   subject: string,   template: string,   context: T }  async emailSend(mailData:IMail<T>) {     const urlConfirmAddress = this.configService.get<string>(       'URL_CONFIRM_ADDRESS',     );      return this.mailerService.sendMail({       to: mailData.to,       subject: mailData.subject,       template: join(__dirname, '/../templates', mailData.template),       context: mailData.context     }).catch((e) => {       throw new HttpException(         `Ошибка работы почты: ${JSON.stringify(e)}`,         HttpStatus.UNPROCESSABLE_ENTITY,       );     });   }

export interface IMail<T> { to: string subject: string, template: string, context: T } async emailSend(mailData:IMail<T>) { const urlConfirmAddress = this.configService.get<string>( 'URL_CONFIRM_ADDRESS', ); return this.mailerService.sendMail({ to: mailData.to, subject: mailData.subject, template: join(__dirname, '/../templates', mailData.template), context: mailData.context }).catch((e) => { throw new HttpException( `Ошибка работы почты: ${JSON.stringify(e)}`, HttpStatus.UNPROCESSABLE_ENTITY, ); }); }

как сделать в IMail context универсальным? потому что интерфейс T изменяемый, как это сделать?

у меня выходит ошибка

Не удается найти имя "T".ts(2304) Параметр "mailData" общего метода из экспортированного класса имеет или использует закрытое имя "T".ts(4073)

Не удается найти имя "T".ts(2304) Параметр "mailData" общего метода из экспортированного класса имеет или использует закрытое имя "T".ts(4073)

Дополнительно:

какой тип у this.mailerService.sendMail ? Надо на него ориентироваться, ты просто передаешь туда context как есть

  • Alexandroppolus,
    import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { MailerService } from '@nestjs-modules/mailer'; import { ConfigService } from '@nestjs/config'; import { join } from 'path'; import { IMail } from './interfaces/mail.interface';  @Injectable() export class MailService {   constructor(     private readonly mailerService: MailerService,     private configService: ConfigService   ) {}    async emailSend(mailData:IMail<T>) {     const urlConfirmAddress = this.configService.get<string>(       'URL_CONFIRM_ADDRESS',     );      return this.mailerService.sendMail({       to: mailData.to,       subject: mailData.subject,       template: join(__dirname, '/../templates', mailData.template),       context: mailData.context     }).catch((e) => {       throw new HttpException(         `Ошибка работы почты: ${JSON.stringify(e)}`,         HttpStatus.UNPROCESSABLE_ENTITY,       );     });   } }

    import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { MailerService } from '@nestjs-modules/mailer'; import { ConfigService } from '@nestjs/config'; import { join } from 'path'; import { IMail } from './interfaces/mail.interface'; @Injectable() export class MailService { constructor( private readonly mailerService: MailerService, private configService: ConfigService ) {} async emailSend(mailData:IMail<T>) { const urlConfirmAddress = this.configService.get<string>( 'URL_CONFIRM_ADDRESS', ); return this.mailerService.sendMail({ to: mailData.to, subject: mailData.subject, template: join(__dirname, '/../templates', mailData.template), context: mailData.context }).catch((e) => { throw new HttpException( `Ошибка работы почты: ${JSON.stringify(e)}`, HttpStatus.UNPROCESSABLE_ENTITY, ); }); } }

  • Александр Иванов, https://github1s.com/nest-modules/mailer/blob/main...
    context?: {     [name: string]: any;   };

    context?: { [name: string]: any; };

    итого ты можешь просто написать

    export interface IMail {   to: string   subject: string,   template: string,   context: Record<string, unknown>; }

    export interface IMail { to: string subject: string, template: string, context: Record<string, unknown>; }

    и не заморачиваться с генериком

  • Alexandroppolus, наверно мы не поняли друг друга, контекст должен принимать в себя любой другой интерфейс, потому то переменные в нем будут меняться по необходимости, я заведомо не могу знать каким он будет
  • Александр Иванов,

    я заведомо не могу знать каким он будет

    Если ты сам не знаешь, то откуда тс это может знать?

  • Александр Иванов, ты просто закидываешь в этот контекст какие-то значения, и потом передаешь его в mailerService.sendMail. Больше никаких действий с ним не в твоем коде не делается.

    mailerService.sendMail готов принять Record< string, unknown >, тебя такой тип тоже устроит, потому незачем что-то придумывать.

  • WbICHA, потому что тс это дед мороз который умеет читать мысли и знает все. я описал выше что пытаюсь сделать, если можно так сказать, универсальную типизацию, т.е. есть главный интерфейс IMail в котором есть элемент context и этот контекст изменяемый, некий T и этот интерфейс T может быть как IEmailUser так и другим передаваемым интерфейсом. чтоб я в конечном итоге мог принимать этот уже "полный" интерфейс, т.е. в данном примере это получается IMail в функции async emailSend(mailData:IMail) и вот как это сделать!
  • Alexandroppolus, меня такой тип не устраивает потому что в context должны передаваться свои поля которые я так же хочу типизировать
  • Александр Иванов, ок, согласен, в sendConfirmMail и тому подобных конкретных функциях можно оставить IMail< IEmailUser > для борьбы с опечатками.
    Ну а в универсальной функции emailSend всё равно будет достаточно IMail< Record< string, unknown > >
    async emailSend(mailData: IMail&lt;Record&lt;string, unknown&gt;&gt;) {

    async emailSend(mailData: IMail&lt;Record&lt;string, unknown&gt;&gt;) {

    как альтернатива, вместо Record< string, unknown > здесь можно перечислить через | все возможные варианты контекста:

    async emailSend(mailData: IMail&lt;IEmailUser | IEmailOther1 | IEmailOther2 | etc&gt;) {

    async emailSend(mailData: IMail&lt;IEmailUser | IEmailOther1 | IEmailOther2 | etc&gt;) {

    но, по моему, это менее гибко.

    ----
    делать emailSend генериком, как предложено в ответе, нет надобности - от этого никаких плюсов. Да и опять же генерик надо будет ограничить типом Record< string, unknown >, чтобы данные можно было передать в mailerService.sendMail

    async emailSend&lt;T extends Record&lt;string, unknown&gt;&gt;(mailData: IMail&lt;T&gt;)

    async emailSend&lt;T extends Record&lt;string, unknown&gt;&gt;(mailData: IMail&lt;T&gt;)

  • Ответы:

    async emailSend<T>(mailData: IMail<T>)

    • я так делал, ошибка пропадает но тогда в context: mailData.context нет отображаются в подсказках переменные из того самого изменяемого интерфейса
    • Александр Иванов, так внутри метода и не известно что пришло. Какую задачу пытаетесь решить?
    • Александр, если можно так сказать, универсальную типизацию, т.е. есть главный интерфейс IMail в котором есть элемент context и этот контекст изменяемый, некий T и этот интерфейс T может быть как IEmailUser так и другим передаваемым интерфейсом. чтоб я в конечном итоге мог принимать этот уже "полный" интерфейс, т.е. в данном примере это получается IMail в функции async emailSend(mailData:IMail) и вот как это сделать!
    • Александр Иванов, у тебя это уже сделано... Ты не понимаешь чего ты хочешь.
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Юрий Linux Ответ

    Для сделать тип универсальным в языке программирования PHP, можно использовать ключевое слово "mixed" в объявлении типа переменной или возвращаемом значении функции. Ключевое слово "mixed" позволяет указать, что переменная может содержать значения различных типов данных.

    Пример использования ключевого слова "mixed":

    function exampleFunction(): mixed {
        $randomValue = rand(0, 1);
     
        if ($randomValue === 0) {
            return "Hello, World!";
        } else {
            return 42;
        }
    }
     
    $exampleVariable = exampleFunction();
     
    if (is_string($exampleVariable)) {
        echo "String value: " . $exampleVariable;
    } elseif (is_int($exampleVariable)) {
        echo "Integer value: " . $exampleVariable;
    }

    function exampleFunction(): mixed { $randomValue = rand(0, 1); if ($randomValue === 0) { return "Hello, World!"; } else { return 42; } } $exampleVariable = exampleFunction(); if (is_string($exampleVariable)) { echo "String value: " . $exampleVariable; } elseif (is_int($exampleVariable)) { echo "Integer value: " . $exampleVariable; }

    В приведенном примере функция exampleFunction возвращает значение типа "mixed", которое может быть как строкой, так и целым числом. После вызова функции, мы проверяем тип возвращаемого значения с помощью функций is_string и is_int, и далее выводим соответствующее сообщение в зависимости от типа данных.

    Используя ключевое слово "mixed", можно сделать тип переменной или возвращаемого значения функции более универсальным и гибким, что может быть полезно в случаях, когда тип данных может быть неопределенным или изменчивым.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно