এলিমেন্টটির স্পষ্টতই একটি 'কোনও' টাইপ রয়েছে কারণ 'স্ট্রিং' টাইপের এক্সপ্রেশনটি সূচকে ব্যবহার করা যায় না


98

একটি প্রতিক্রিয়া প্রকল্পের জন্য টাইপস্ক্রিপ্ট চেষ্টা করে দেখছি এবং আমি এই ত্রুটিটিতে আটকে রয়েছি:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ train_1: boolean; train_2: boolean; train_3: boolean; train_4: boolean; }'.
  No index signature with a parameter of type 'string' was found on type '{ train_1: boolean; train_2: boolean; train_3: boolean; train_4: boolean; }'

আমি যখন আমার উপাদানগুলিতে অ্যারে ফিল্টার করার চেষ্টা করি তখন এটি উপস্থিত হয়

.filter(({ name }) => plotOptions[name]);

এখন পর্যন্ত আমি "টাইপসক্রিপ্টে ইনডেক্সিং অবজেক্টস" ( https://dev.to/kingdaro/indexing-objects-in-typescript-1cgi ) নিবন্ধটি দেখেছি কারণ এটিতে অনুরূপ ত্রুটি ছিল, তবে আমি সূচী স্বাক্ষরটিতে যুক্ত করার চেষ্টা করেছি টাইপ করুন plotTypesএবং আমি এখনও একই ত্রুটি পেয়েছি।

আমার উপাদান কোড:

import React, { Component } from "react";
import createPlotlyComponent from "react-plotly.js/factory";
import Plotly from "plotly.js-basic-dist";
const Plot = createPlotlyComponent(Plotly);

interface IProps {
  data: any;
}

interface IState {
  [key: string]: plotTypes;
  plotOptions: plotTypes;
}

type plotTypes = {
  [key: string]: boolean;
  train_1: boolean;
  train_2: boolean;
  train_3: boolean;
  train_4: boolean;
};

interface trainInfo {
  name: string;
  x: Array<number>;
  y: Array<number>;
  type: string;
  mode: string;
}

class FiltrationPlots extends Component<IProps, IState> {
  readonly state = {
    plotOptions: {
      train_1: true,
      train_2: true,
      train_3: true,
      train_4: true
    }
  };
  render() {
    const { data } = this.props;
    const { plotOptions } = this.state;

    if (data.filtrationData) {
      const plotData: Array<trainInfo> = [
        {
          name: "train_1",
          x: data.filtrationData.map((i: any) => i["1-CumVol"]),
          y: data.filtrationData.map((i: any) => i["1-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_2",
          x: data.filtrationData.map((i: any) => i["2-CumVol"]),
          y: data.filtrationData.map((i: any) => i["2-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_3",
          x: data.filtrationData.map((i: any) => i["3-CumVol"]),
          y: data.filtrationData.map((i: any) => i["3-PressureA"]),
          type: "scatter",
          mode: "lines"
        },
        {
          name: "train_4",
          x: data.filtrationData.map((i: any) => i["4-CumVol"]),
          y: data.filtrationData.map((i: any) => i["4-PressureA"]),
          type: "scatter",
          mode: "lines"
        }
      ].filter(({ name }) => plotOptions[name]);
      return (
        <Plot
          data={plotData}
          layout={{ width: 1000, height: 1000, title: "A Fancy Plot" }}
        />
      );
    } else {
      return <h1>No Data Loaded</h1>;
    }
  }
}

export default FiltrationPlots;

উত্তর:


101

আপনি plotOptionsস্ট্রিং ব্যবহার করে সম্পত্তি অ্যাক্সেস করার চেষ্টা করার কারণে এটি ঘটে name। টাইপসক্রিপ্ট বুঝতে nameপারে যে এর কোনও মান থাকতে পারে, কেবলমাত্র সম্পত্তির নাম থেকে নয় plotOptions। সুতরাং টাইপসক্রিপ্টের জন্য সূচক স্বাক্ষর যুক্ত করতে হবে plotOptions, সুতরাং এটি জানে যে আপনি কোনও সম্পত্তি নাম ব্যবহার করতে পারেন plotOptions। তবে আমি ধরণের পরিবর্তন করার পরামর্শ দিচ্ছি name, সুতরাং এটি কেবল plotOptionsবৈশিষ্ট্যগুলির মধ্যে একটি হতে পারে।

interface trainInfo {
    name: keyof typeof plotOptions;
    x: Array<number>;
    y: Array<number>;
    type: string;
    mode: string;
}

এখন আপনি কেবলমাত্র বিদ্যমান নাম ব্যবহার করতে সক্ষম হবেন plotOptions

আপনার কোডটিও সামান্য পরিবর্তন করতে হবে।

প্রথমে কিছু অস্থায়ী ভেরিয়েবলকে অ্যারের বরাদ্দ করুন, তাই টিএস অ্যারে প্রকারটি জানে:

const plotDataTemp: Array<trainInfo> = [
    {
      name: "train_1",
      x: data.filtrationData.map((i: any) => i["1-CumVol"]),
      y: data.filtrationData.map((i: any) => i["1-PressureA"]),
      type: "scatter",
      mode: "lines"
    },
    // ...
}

তারপরে ফিল্টার করুন:

const plotData = plotDataTemp.filter(({ name }) => plotOptions[name]);

আপনি যদি API থেকে ডেটা পেয়ে থাকেন এবং সংকলনের সময় চেক প্রপস টাইপ করার কোনও উপায় না থাকে তবে আপনার সূচীতে স্বাক্ষর যুক্ত করার একমাত্র উপায় হ'ল plotOptions:

type tplotOptions = {
    [key: string]: boolean
}

const plotOptions: tplotOptions = {
    train_1: true,
    train_2: true,
    train_3: true,
    train_4: true
}

34
// bad
const _getKeyValue = (key: string) => (obj: object) => obj[key];

// better
const _getKeyValue_ = (key: string) => (obj: Record<string, any>) => obj[key];

// best
const getKeyValue = <T extends object, U extends keyof T>(key: U) => (obj: T) =>
  obj[key];

খারাপ - ত্রুটির কারণ হ'ল objectধরণটি হ'ল ডিফল্টরূপে একটি খালি অবজেক্ট। সুতরাং stringসূচিতে কোনও প্রকার ব্যবহার করা সম্ভব নয় {}

আরও ভাল - কারণ ত্রুটিটি অদৃশ্য হয়ে যায় কারণ এখন আমরা সংকলকটি বলছি objআর্গুমেন্টটি স্ট্রিং / মান ( string/any) জোড়গুলির সংকলন হবে । তবে, আমরা anyটাইপটি ব্যবহার করছি , তাই আমরা আরও ভাল করতে পারি।

সেরা - Tখালি বস্তু প্রসারিত। Uএর চাবিগুলি প্রসারিত করে T। অতএব Uসর্বদা বিদ্যমান থাকবে T, সুতরাং এটি চেহারা হিসাবে মূল্য হিসাবে ব্যবহার করা যেতে পারে।

এখানে একটি সম্পূর্ণ উদাহরণ:

জেনেরিকের ক্রমটি গুরুত্বপূর্ণ নয় বলে জেনারিকের ক্রমটি ( U extends keyof Tএখন আগে এসেছে T extends object) স্যুইচ করেছি আমি আপনাকে একটি ক্রম নির্বাচন করতে হবে যা আপনার ফাংশনটির জন্য সর্বাধিক অর্থবোধ করে।

const getKeyValue = <U extends keyof T, T extends object>(key: U) => (obj: T) =>
  obj[key];

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Smith",
  age: 20
};

const getUserName = getKeyValue<keyof User, User>("name")(user);

// => 'John Smith'

বিকল্প সিনট্যাক্স

const getKeyValue = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];

4
যারা টাইপস্ক্রিপ্টে নতুন তাদের জন্য এই কাজটি আরও সহজ করার জন্য আমি এই ফাংশনটির সাথে একটি ছোট এনপিএম প্যাকেজ লিখেছি।
অ্যালেক্স মেকে

প্যাকেজটি প্রায় 38 বাইট একবার প্যাকেজড এবং মিনিফাইন্ড হয়।
অ্যালেক্স মেকে

4
অ্যালেক্স, দেখা যাচ্ছে যে আপনার স্কেলটি সবচেয়ে খারাপ থেকে সর্বোত্তম পর্যন্ত কোনও স্কেলকে সংক্ষিপ্ত এবং সাধারণ থেকে প্রলিক্স প্রতীক-সালাদে কেবল একটি মাসোসিস্টই পছন্দ করতে পারে appro এই চেতনায়, এখানে একটি "বেস্টার" সংস্করণ রয়েছে, যা কেবলমাত্র আপনার "সেরা" সংস্করণটি নকল এবং বদলে গেছে:d ee((oent V[jkkncnt=kfay u skk==e>Ugs(< :ds b]uUeT eKne e=x>:dTy: lc,n=b;T=by>o[x oo<U yc ,t Ketgt )c)yo oe eTV aej ; Txb )t> se de esytkjeeUe otj]b j o:oebe)ytlT(eejfs>toyn> x
ওয়েববি



5

যখন আমরা এই বিষয়টিকে [কী] এর মতো কিছু করি তখন টাইপস্ক্রিপ্ট নিশ্চিতভাবে জানতে পারে না যে কীটি সেই বস্তুর মধ্যে রয়েছে কিনা। আমি কি করেছিলাম:

Object.entries(data).forEach(item => {
    formData.append(item[0], item[1]);
});

0

আউট typescriptত্রুটি সহ

    const formData = new FormData();
    Object.keys(newCategory).map((k,i)=>{  
        var d =Object.values(newCategory)[i];
        formData.append(k,d) 
    })

0

অ্যালেক্স ম্যাকেয়কে ধন্যবাদ আমার ডাইনামিক প্রপস সেট করার জন্য একটি সংকল্প ছিল:

  for(let prop in filter)
      (state.filter as Record<string, any>)[prop] = filter[prop];

0

আমি অ্যালেক্স ম্যাকের ফাংশন / ব্যবহারে কিছু ছোট পরিবর্তন করেছি যা আমার মনে হয় যে এটি কেন কাজ করে তা অনুসরণ করা কিছুটা সহজ করে তোলে এবং ব্যবহারের আগে-সংজ্ঞায়িত নিয়মটিও মেনে চলে ।

প্রথমে এই ফাংশনটি ব্যবহারের জন্য সংজ্ঞা দিন:

const getKeyValue = function<T extends object, U extends keyof T> (obj: T, key: U) { return obj[key] }

যেভাবে আমি এটি লিখেছি, ফাংশনের জেনেরিকটি প্রথমে বস্তুর তালিকা তৈরি করে, তারপরে দ্বিতীয় বস্তুর উপরের সম্পত্তি (এগুলি কোনও ক্রমে ঘটতে পারে তবে আপনি যদি নিয়ম ভাঙার U extends key of Tআগে নির্দিষ্ট করে থাকেন , এবং এটি ঠিক বোঝা যায়) অবজেক্টটি প্রথম এবং তার 'সম্পত্তি দ্বিতীয়টি' রাখতে Finally অবশেষে, আমি তীর অপারেটরগুলির পরিবর্তে আরও সাধারণ ফাংশন সিনট্যাক্স ব্যবহার করেছি ( )।T extends objectno-use-before-define=>

যাইহোক, এই পরিবর্তনগুলির সাথে আপনি কেবল এটির মতো এটি ব্যবহার করতে পারেন:

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Smith",
  age: 20
};

getKeyValue(user, "name")

যা আবার আমি আরও কিছুটা পঠনযোগ্য বলে মনে করি।


-11

এটি আমার পক্ষে কাজ করেছিল। tsconfig.jsonএকটি বিকল্প আছে noImplicitAnyযে এটি ছিল true, আমি শুধু শুধু এটি সেট falseএবং এখন আমি স্ট্রিং ব্যবহার বস্তু বৈশিষ্ট্য অ্যাক্সেস করতে পারেন।


7
এটি কঠোরভাবে সরিয়ে ফেলবে, তবে টাইপসক্রিপ্টটি ব্যবহার করার কোনও মানে নেই যদি আমরা এই সীমাবদ্ধতাগুলি সরিয়ে রাখি।
জোসেফ ব্রিগেস

আমি @ জোসেফব্রিগসকে সম্মতি দিচ্ছি না। টাইপস্ক্রিপ্ট টেবিল এ নিয়ে আসে অন্যান্য অনেক সুবিধা। প্রকারের চেক এর মধ্যে একটি। আপনার প্রকল্পের প্রয়োজনীয়তার উপর নির্ভর করে আপনি অপ্ট-ইন বা আউটআউট করতে পারেন তা দুর্দান্ত।
জেক

15
এটি সমস্যার সমাধান করে না, এটি কেবল এটি উপেক্ষা করে।
আজকের দিন 21

4
@ জেক আমি সাথী বুঝি :) আমি রাশ লেখায় ছিলাম writing আমার অভিপ্রায়টি হ'ল আমরা যদি কেবল এটিকে উপেক্ষা করার কথা বলে সমস্যাগুলি সমাধান করতে থাকি তবে প্রথমে এর কোনও অর্থ নেই। কিন্তু তারপরে আবার সবগুলি প্রকল্পের উপর নির্ভর করে এবং প্রতিটি প্রকল্পের সিদ্ধান্তের উপর নির্ভর করে।
জোসেফ ব্রিগেস

আমি এটি পছন্দ করি ... এমনকি সি # এর মতো "শক্ত" মতো শক্তিশালী ভাষাও। উল্লেখ করা stackoverflow.com/questions/62377614/... ... একটি ওভার একটি সহজ সম্পত্তি অ্যাক্সেস করতে কোড bumping সব সাজানোর লাগাতে engineered বিট।
এরিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.