Answer by Egypt Acosta
error TS2554: Expected 1 arguments, but got 0.,
Tracking changes to code for personal use
,when the class instance is called. How can I fix this?,Thanks for contributing an answer to Stack Overflow!
Angular automatically resolve dependencies of components and services. However, when you call your class
like that:
const instance = new ErrorHandler().getError();
Then you need to supply a dependency BackendErrorsService
. Something like that:
let backendErrorsService = new BackendErrorsService();
const instance = new ErrorHandler(backendErrorsService ).getError();
Answer by Hazel Huber
Implement their own constructor that invokes the ViewModel base class constructor,It’s also worth noting that we’re calling super in the NewConstructorViewModel constructor. This invokes the constructor of the ViewModel base (or “super”) class. TypeScript enforces that we pass the appropriate arguments (in our case a single string).,Not implement a constructor at all, leaving the base class constructor to become the default constructor of the subclass,Having done that, let’s try subclassing and implementing a new constructor that has two parameters (to differentiate from the constructor we’re overriding):
To dig into this, let’s create a scratchpad project to work with. We’re going to create a Node.js project and install TypeScript as a dependency.
mkdir ts-abstract-constructors
cd ts-abstract-constructors
npm init --yes
npm install typescript @types/node --save-dev
We now have a package.json
file set up. We need to initialize a TypeScript project as well:
npx tsc --init
This will give us a tsconfig.json
file that will drive configuration of TypeScript. By default, TypeScript transpiles to an older version of JavaScript that predates classes. So we’ll update the config to target a newer version of the language that does include them:
"target": "es2020",
"lib": ["es2020"],
Finally we’ll add a script to our package.json
that compiles our TypeScript to JavaScript and then runs the JS with node:
"start": "tsc --project "." && node index.js"
Now we’re ready. Let’s add an abstract class with a constructor to our index.ts
file:
abstract class ViewModel {
id: string;
constructor(id: string) {
this.id = id;
}
}
First of all, can we instantiate our abstract class? We shouldn’t be able to do this:
const viewModel = new ViewModel('my-id');
console.log(`the id is: ${viewModel.id}`);
Sure enough, running npm start
results in the following error (which is also being reported by our editor, VS Code).
index.ts:9:19 - error TS2511: Cannot create an instance of an abstract class.
const viewModel = new ViewModel('my-id');
Tremendous. However, it’s worth remembering that abstract
is a TypeScript concept. When we compile our TS, although it’s throwing a compilation error, it still transpiles an index.js
file that looks like this:
"use strict";
class ViewModel {
constructor(id) {
this.id = id;
}
}
const viewModel = new ViewModel('my-id');
console.log(`the id is: ${viewModel.id}`);
As we can see, there’s no mention of abstract
; it’s just a straightforward class
. In fact, if we directly execute the file with node index.js
we can see an output of:
the id is: my-id
Let’s now create our first subclass of ViewModel
and attempt to instantiate it:
class NoNewConstructorViewModel extends ViewModel {
}
// error TS2554: Expected 1 arguments, but got 0.
const viewModel1 = new NoNewConstructorViewModel();
const viewModel2 = new NoNewConstructorViewModel('my-id');
Having done that, let’s try subclassing and implementing a new constructor that has two parameters (to differentiate from the constructor we’re overriding):
class NewConstructorViewModel extends ViewModel {
data: string;
constructor(id: string, data: string) {
super(id);
this.data = data;
}
}
// error TS2554: Expected 2 arguments, but got 0.
const viewModel3 = new NewConstructorViewModel();
// error TS2554: Expected 2 arguments, but got 1.
const viewModel4 = new NewConstructorViewModel('my-id');
const viewModel5 = new NewConstructorViewModel('my-id', 'important info');
Answer by Daxton Doyle
To get around this, you can specifically add runtime checks to ensure that the thrown type matches your expected type.
Otherwise, you can just use a type assertion, add an explicit : any to your catch variable, or turn off —useUnknownInCatchVariables.,Alternatively, you can either specify an explicit type annotation on the callback argument:,You can see the specific changes in the original pull request.,As a workaround, you can add an explicit constraint of {} to a type parameter to get the old behavior.
// Imagine this is our imported module, and it has an export named 'foo'.
let fooModule = {
foo() {
console.log(this);
}
};
fooModule.foo();
Answer by Dion Brock
I want to get the string value in model,Spec, create a mock component so that fl-navigation can compile without errors:,Hi. What is the recommended way to get access to an input’s model in a directive? As far as I can know, I can use,How do I cancel a value being written into my input with ngcontrol? I have a piece of code like this:
this.profileBankingService.getBankingInfoDetails()
.subscribe(
data => {
this.profileBankingService.addChildObjects(data.links);
this.profileBankingService.addLabelList(data.labels);
this.bankInfoDetails = data.body[0];
this.disclaimerTxt = data.body[1].split('<P>').join('').split('</P>').join('').trim();
this.disclaimerTxt = this.disclaimerTxt.replace('Submit', 'Save');
for (let bankInfoDetail of this.bankInfoDetails) {
bankInfoDetail.accountForDisplay = bankInfoDetail.accountForDisplay.replace(/&/g, "&");
//bankInfoDetail.bankAccountNumber = bankInfoDetail.bankAccountNumber.replace(/.(?=.{3,}$)/g, '*');
bankInfoDetail.displayAccountNumber = bankInfoDetail.bankAccountNumber.replace(/.(?=.{3,}$)/g, '*');
}
this.loading = false;
},
Answer by Kallie Carr
This is a follow-up to a tutorial on mocking calls to a Neo4j database using neo-forgery. The technique shown there to mock a call works beautifully when you explicitly run a query using a declared session.,You probably would benefit from the tutorial on mocking calls to a neo4j database if you want to see more detail about using neo-forgery.,The Getting Started tutorial adds the following books array and resolver rather than a database.,But if you are using directives with an Apollo Server, you will need to mock the driver itself.
(1) Run these commands in a terminal to create a project with the AVA test runner using TypeScript:
mkdir movies # make the code base directorycd movies # move to the directorynpm init -y # create a package.json filenpm init ava # add the AVA testrunnernpm i -D typescript ts-node # add TypeScriptmkdir test # a folder for testsmkdir src # a folder for source code
(2) Add this AVA specification to your package.json
to use AVA with typescript, and to specify a test directory with files to test:
"ava": { "files": [ "test/**/*.test.ts" ], "extensions": [ "ts" ], "require": [ "ts-node/register" ]},
(3) Add a tsconfig.json
file with the following contents to enable certain things when we begin coding:
{ "compilerOptions": { "declaration": true, "importHelpers": true, "module": "commonjs", "outDir": "lib", "rootDirs": ["./src", "./test"], "strict": true, "target": "es2017" }, "include": [ "src/**/*" ]}
(1) Add some packages to work with Apollo and neo4j.
npm install apollo-server graphql # server and graphqlnpm i neo4j-driver @neo4j/graphql # neo4j capabilitynpm i dotenv # lets us store credentials in # an env filenpm i -D neo-forgery # the mocking tool
(2) Create the following src/index.ts file:
require('dotenv').config();const neo4j = require('neo4j-driver');import { Neo4jGraphQL } from '@neo4j/graphql';import {ApolloServer} from "apollo-server";const { gql } = require('apollo-server');const typeDefs = gql` type Book { title: String author: String }`;const schema = new Neo4jGraphQL({ typeDefs,}).schema;const driver = neo4j.driver( process.env.DB_URI, neo4j.auth.basic( process.env.DB_USER, process.env.DB_PASSWORD, ),);function context({ event, context }: { event: any, context: any }): any { return ({ event, context, driver, });}const server:ApolloServer = new ApolloServer( { schema, context, });// @ts-ignoreserver.listen().then(({ url }) => { console.log(`? Server ready at ${url}`);});
Answer by Ariana Velasquez
Is it possible to have a derived class which takes different parameters to its constructor than its base class? I’m getting errors when trying to call super:,Class ‘Derived’ incorrectly extends base class ‘Base’.
Types have separate declarations of a private property ‘_myService’.,ERRORTS2341: Property ‘_myService’ is private and only accessible within class ‘BaseClass’.,Don’t duplicate private in the derived class. Fixed example:
Is it possible to have a derived class which takes different parameters to its constructor than its base class? I’m getting errors when trying to call super
:
class Base {
constructor (private _myService) {}
}
class Derived extends Base {
constructor (private _myService, private _myOtherService) {
super(_myService);
}
}
Class ‘Derived’ incorrectly extends base class ‘Base’.
Types have separate declarations of a private property ‘_myService’.
class Derived extends Base {
constructor (_myService, private _myOtherService) {
super(_myService);
}
}
ERRORTS2341: Property ‘_myService’ is private and only accessible within class ‘BaseClass’.
class Derived extends Base {
constructor (private _myOtherService) {
super();
}
}
Есть код, в котором данные о заказе отправляются на электронную почту. Код:
import { Component, OnInit } from '@angular/core';
import { ProductService } from '../shared/product.service';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { OrderService } from '../shared/order.service';
import emailjs, { EmailJSResponseStatus } from 'emailjs-com';
@Component({
selector: 'app-cart-page',
templateUrl: './cart-page.component.html',
styleUrls: ['./cart-page.component.scss']
})
export class CartPageComponent implements OnInit {
cartProducts = []
totalPrice = 0
added = ''
form : FormGroup
submitted = false
constructor(
private productServ : ProductService,
private orderServ : OrderService
) { }
ngOnInit() {
this.cartProducts = this.productServ.cartProducts
for (let i = 0; i < this.cartProducts.length; i++) {
this.totalPrice += +this.cartProducts[i].price
}
this.form = new FormGroup({
name: new FormControl(null, Validators.required),
phone: new FormControl(null, Validators.required),
address: new FormControl(null, Validators.required),
payment: new FormControl('Cash'),
})
}
public sendEmail($event: Event) {
if (this.form.invalid) {
return
}
this.submitted = true
const order = {
name: this.form.value.name,
phone: this.form.value.phone,
address: this.form.value.address,
payment: this.form.value.payment,
orders: this.cartProducts,
price: this.totalPrice,
date: new Date()
}
emailjs.sendForm('service_lkw4wsl', 'template_rtee3qn', toString(order), 'user_4dZI6eHowyywWMEMQGidG')
this.orderServ.create(order).subscribe( res => {
this.added = 'Delivery is framed'
this.submitted = false
})
}
delete(product) {
this.totalPrice -= +product.price
this.cartProducts.splice(this.cartProducts.indexOf(product), 1)
}
}
Но при компиляции выдаёт ошибку:
ERROR in src/app/cart-page/cart-page.component.ts(56,70): error TS2554: Expected 0 arguments, but got 1.
Проект доступен на ГитХаб — https://github.com/FastGameDev/Shop.git
Заранее спасибо!!!
#javascript #reactjs #typescript #use-context #use-reducer
Вопрос:
У меня есть несколько обучающих программ и useContext, в которых я получаю ошибки, аналогичные приведенным ниже (TS2554). Я выбрал authReducer, так как он самый простой. Я получаю одну и ту же ошибку при каждой отправке действия. Я поиграл, рассматривая другие решения и пробуя их, Добавил еще несколько определений, но ясно, что я делаю не то, что должен делать!
Это мой первый проект, над которым я работаю с машинописным текстом, так что полегче со мной!
насколько я могу судить, Диспетчерская не ожидает никаких аргументов, но получает их. Однако, когда я объявляю свой authReducer, он имеет аргумент действия типа Действия и возвращает состояние аутентификации.
/AuthState.tsx:40:16 - error TS2554: Expected 0 arguments, but got 1.
40 dispatch({
41 type: USER_LOADED,
42 payload: res.data,
43 });
authReducer.tsx
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT,
CLEAR_ERRORS,
} from '../types';
import { initialState } from './AuthState';
type Actions =
| {
type: 'USER_LOADED';
payload: {
name: string;
id: string;
};
}
| {
type: 'AUTH_ERROR';
payload?: string;
}
| {
type: 'LOGIN_SUCCESS';
payload: { token: string };
}
| {
type: 'LOGIN_FAIL';
payload: string;
}
| {
type: 'LOGOUT';
payload?: string;
}
| {
type: 'CLEAR_ERRORS';
};
interface AuthState {
token?: string | null;
isAuthenticated?: boolean;
loading: boolean;
user?: {
name: string;
id: string;
} | null;
error?: string | undefined | null;
}
const AuthReducer = (
state: typeof initialState,
action: Actions
): AuthState => {
switch (action.type) {
case USER_LOADED:
return {
...state,
isAuthenticated: true,
loading: false,
user: action.payload,
};
case LOGIN_SUCCESS:
localStorage.setItem('token', action.payload.token);
return {
...state,
...action.payload,
isAuthenticated: true,
loading: false,
};
case AUTH_ERROR:
case LOGIN_FAIL:
case LOGOUT:
localStorage.removeItem('token');
return {
...state,
token: null,
isAuthenticated: false,
loading: false,
user: null,
error: action.payload,
};
case CLEAR_ERRORS:
return {
...state,
error: null,
};
default:
return state;
}
};
export default AuthReducer;
AuthContext.tsx
import { createContext } from 'react';
import { initialState } from './AuthState';
type authContextType = {
loadUser: () => Promise<void> | null;
login: (formData: {
email: string;
password: string;
}) => Promise<void> | null;
logout: () => void;
clearErrors: () => void;
error: string | null;
isAuthenticated: boolean;
loading: boolean;
user: {
name: string;
id: string;
};
token: string;
};
const authContext = createContext<authContextType>(initialState); //TODO A more robust type is possible
export default authContext;
AuthState.tsx
import React, { useReducer } from 'react';
import axios from 'axios';
import AuthContext from './AuthContext';
import AuthReducer from './AuthReducer';
import setAuthToken from '../../utils/setAuthToken';
import {
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT,
CLEAR_ERRORS,
} from '../types';
export const initialState = {
loadUser: null,
login: null,
logout: () => {},
clearErrors: () => {},
token: localStorage.getItem('token'),
isAuthenticated: null,
loading: true,
error: null,
user: null,
};
const AuthState: React.FC = ({ children }) => {
const [state, dispatch] = useReducer(AuthReducer, initialState);
//Load User
const loadUser = async () => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('api/auth');
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({ type: AUTH_ERROR });
}
};
//Login User
const login = async (formData: { email: string; password: string }) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
try {
const res = await axios.post('/api/auth', formData, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
loadUser();
} catch (err) {
dispatch({
type: LOGIN_FAIL,
payload: err.response.data.msg,
});
}
};
//Logout
const logout = () => {
dispatch({ type: LOGOUT });
};
//Clear Errors
const clearErrors = () => {
dispatch({ type: CLEAR_ERRORS });
};
return (
<AuthContext.Provider
value={{
token: state.token,
isAuthenticated: state.isAuthenticated,
loading: state.loading,
user: state.user,
error: state.error,
loadUser,
login,
logout,
clearErrors,
}}
>
{children}
</AuthContext.Provider>
);
};
export default AuthState;
Комментарии:
1.
state: typeof initialState,
хотя эта линия выглядит неправильно, не так лиstate: typeof AuthState,
?2. Эй, Том, спасибо за ответ. Я попробовал и поиграл еще немного, но, к сожалению, это, похоже, не повлияло на данную ошибку
3. Я больше не вижу ничего странного -> не могли бы вы сказать мне, что >
USER_LOADED
находится в../types
папке
Ответ №1:
Проблема в том, что здесь:
const AuthReducer = (
state: typeof initialState,
action: Actions
): AuthState ...
typescript не может связать ваши типы typeof initialState
и AuthState
. Но useReducer
перегрузки зависят от типа reducer
вывода правильного типа результата.
Здесь у вас есть несколько вариантов рефакторинга. Вы можете просто сказать typescript, что это одни и те же типы:
const AuthReducer = (
state: AuthState,
action: Actions
): AuthState
или сделайте свой initialState
тип немного более расслабленным:
const initialState: AuthState = {....}
Суть проблемы заключается в том, что типы TypeofA
и A
:
const a = { a: null }
type TypeofA = typeof a
type A = { a: string | null }
это не совсем одно и то же. Вы теряете | string
при объявлении поля просто как null
. Чтобы сделать их равными, вы можете либо написать a
объект с утверждениями типа:
const a = { a: null as string | null }
или прямо указать тип a
:
const a: A = { a: null }