Ошибка компиляции Typescript, даже если параметры имеют правильный тип - PullRequest
0 голосов
/ 27 апреля 2019

Typescript выдает эту ошибку компиляции:

Argument of type '(state: string, action: Action<string>) => string' is not assignable to parameter of type 'Reducer<string, Action<string>>'.
  Types of parameters 'state' and 'state' are incompatible.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.  TS2345

и моя функция выглядит следующим образом:

function todos(state: string, action: Action<string>)

Что я не могу понять, так это, во-первых, параметр stateпока не обнуляется, но компилятор говорит, что этоВо-вторых, сообщение об ошибке противоречит самому себе, говоря в первой строке, что тип функции (state: string, action: Action<string>) => string (что правильно), тогда как в третьей строке говорится, что первый параметр string | undefined!

I'mЯ только начинаю изучать машинопись и реагировать на избыточность, поэтому я в замешательстве.

РЕДАКТИРОВАТЬ:

Далее я попытался вызвать функцию, передающую undefined в качестве первого аргумента, нокомпилятор жалуется, что он не обнуляется, как ожидалось, но позже жалуется, что он обнуляем!

РЕДАКТИРОВАТЬ 2

Я забыл сказать, что я использую todosфункция при вызове функции createStore из избыточного кода выглядит следующим образом: createStore(todos).

Полный код такой:

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {Action, createStore} from 'redux'
import {Provider} from "react-redux";

function todos(state: string, action: Action<string>) {
    return state
}

let store = createStore(todos); // PROBLEM HERE
let app = (
    <Provider store={store}>
        <App/>
    </Provider>
)

ReactDOM.render(app, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();

Кроме того, я знаю, что combineReducers обычнои что state не должно быть string, но я задаю этот вопрос исключительно из любопытства (будучи новичком в машинописи), потому что я знаю, что есть очевидные обходные пути.

Я такжепопытался использовать string[] в качестве типа состояния, но свыдается ошибка ame, за исключением того, что в это время string[] | undefined.

РЕДАКТИРОВАТЬ 3:

Я понял, что если я добавлю значение по умолчанию в состояние, например function todos(state: string = "", action: Action), ошибка исчезнет.Но почему это?Разве это не избыточно, учитывая, что состояние уже является обязательным ненулевым параметром?В Swift и Kotlin ошибка будет выдана только в том случае, если вы вызываете функцию todos с аргументом состояния nil, но вам не нужно указывать значение по умолчанию в определении параметра.Так почему же это так в машинописи?Это дизайн?

1 Ответ

1 голос
/ 27 апреля 2019

Отвечая на ваш точный вопрос, упомянутый в EDIT 3, сделав параметр функции по умолчанию (как вы сделали, указав значение по умолчанию для state), измените тип такого параметра на string | undefined (в вашем случае).Это также эквивалентно вопросительному знаку после параметра.Таким образом, подписи вызовов трех функций ниже одинаковы

function todos(state: string | undefined, action: Action<string>)
function todos(state?: string, action: Action<string>)  // This example is not completly correct as you should make action optional too, by addint ? to it name
function todos(state: string = "", action: Action<string>)

Я предлагаю эту главу из документа Typescript.

Ошибка в начале этой темы гласит, что Type 'string | undefined' is not assignable to type 'string'. Таким образом, добавление значения по умолчанию к state делает его типа string | undefined, который удовлетворяет компилятору.

...