Flow中的歧视/不相交联盟

时间:2017-07-29 16:10:24

标签: flowtype

Sample errors

我试图让Flow感到高兴。

不是很好,给我这个:

app/components/commands/types.js:117
117:   { state: 'state-retries-timeout',
                ^^^^^^^^^^^^^^^^^^^^^^^ string literal `state-retries-timeout`. Expected string literal `state-initial`, got `state-retries-timeout` instead
 60:   { state: 'state-initial', touched: boolean }

但我不明白我是如何不遵循documentation

源代码:

// @flow

/**
 * A server-side validation message. Should contain a globally unique key
 * and a message. The key can be used for internationalisation purposes.
 */
export type ValidationMessage =
  { key: string,
    message: string }

export function validationMessage(key: string, message: string): ValidationMessage {
  return { key, message }
}

/**
 * The field is untouched in this user-session.
 */
export const StateInitial = 'state-initial';

/**
 * The edit is not yet persisted anywhere.
 */
export const StatePending = 'state-pending'
/**
 * The command is not yet committed on the server, but is committed locally.
 */
export const StatePendingSavedLocally = 'state-pending-saved-locally'
/**
 * The command was successfully commited.
 */
export const StateSuccess = 'state-success'
/**
 * The command was commited, but there are resulting warnings.
 */
export const StateSuccessWarnings  = 'state-success-warnings'
/**
 * The command or its data was invalid and the server returned 400 Bad Request;
 * it may not be retried without changing it.
 */
export const StateRejected = 'state-rejected'

/**
 * Despite numerous retries, the app failed to persist the change to the server.
 */
export const StateRetriesTimeout = 'state-retries-timeout'

export type Initial =
  { state: 'state-initial',
    touched: boolean }

export type Pending =
  { state: 'state-pending',
    touched: boolean }

export type PendingSavedLocally =
  { state: 'state-pending-saved-locally',
    touched: boolean }

export type Success =
  { state: 'state-success',
    touched: boolean }

export type SuccessWarnings =
  { state: 'state-success-warnings',
    warnings: ValidationMessage[],
    touched: boolean }

export type Rejected =
  { state: 'state-rejected',
    errors: ValidationMessage[],
    touched: boolean }

export type RetriesTimeout =
  { state: 'state-retries-timeout',
    touched: boolean }

/**
 * The discriminated union of all states we allow fields to be represented as.
 */
export type ValueChangeState =
  | Initial
  | Pending
  | PendingSavedLocally
  | Success
  | SuccessWarnings
  | Rejected
  | RetriesTimeout

export const initial: ValueChangeState  =
  { state: 'state-initial',
    touched: false }

export const pending: ValueChangeState =
  { state: 'state-pending',
    touched: true }

export const pendingSavedLocally: ValueChangeState =
  { state: 'state-pending-saved-locally',
    touched: true }

export const success: ValueChangeState =
  { state: 'state-success',
    touched: true }

export function successWarnings(warnings: ValidationMessage[], touched: boolean = true): ValueChangeState {
  return {
    state: 'state-success-warnings',
    warnings,
    touched
  }
}

export function rejected(errors: ValidationMessage[], touched: boolean = true): ValueChangeState {
  return {
    state: 'state-rejected',
    errors,
    touched
  }
}

export const retriesTimeout: ValueChangeState =
  { state: 'state-retries-timeout',
    touched: true }

样本用法

// @flow
/*eslint no-unused-expressions: 0 */
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { initial, pending } from './types';
import { valueStateReducer } from './reducers';
import { successOf, rejectionOf, timeoutOf, successWarningsOf } from './actions';

describe('(Reducer) components/commands', function() {
  describe('valueStateReducer', function() {
    const noop = () => ({ type: 'NOOP' });
    const testing = () => ({ type: 'commands/TESTING' });
    const subject = valueStateReducer('commands/TESTING');

    it('other makes no change', function() {
      const res = subject(initial, noop());
      expect(res).to.deep.eq(initial);
    });

    it('of action makes pending', function() {
      const res = subject(initial, testing());
      expect(res).to.deep.eq(pending);
    });
  });
});

1 个答案:

答案 0 :(得分:2)

答案是,当提供默认值时,流不能正确处理可空/未定义的区分联合/和类型的破坏性分配。

assignment bug

在此屏幕截图中,我将disp默认为valueState(其中一个DU案例)。这会触发错误。

如果我反而默认下来,那么流量不会是barf:

bug workaround