Skip to content

Structural Subtyping with Control flow based type analysis #10065

Closed
@vvakame

Description

@vvakame

I like --strictNullChecks options.
But this options is very hard to apply existing project.
I want to remove optional operator from interface.
TypeScript 2.0.0 can it! but assignment operation is not under control flow context.
I think we need it.

for example.

declare var fs: { readFileSync(filePath: string, encoding: string): string; };

interface Config {
    filePath?: string;
    verbose?: boolean;
}

// add for --strictNullChecks support. I want use this interface wider.
interface ConfigFixed {
    filePath: string;
    verbose: boolean;
}

function foo(config: Config = {}) {
    config.filePath = config.filePath || "settings.json";
    config.verbose = config.verbose || false;

    // config.filePath is string. ts 2.0.0 is super cool!
    config.filePath;
    // config.verbose is boolean. ts 2.0.0 is very smart!
    config.verbose;

    // but an error occured.
    // test.ts(16,9): error TS2345: Argument of type 'Config' is not assignable to parameter of type 'ConfigFixed'.
    //   Types of property 'filePath' are incompatible.
    //     Type 'string | undefined' is not assignable to type 'string'.
    //       Type 'undefined' is not assignable to type 'string'.
    bar(config);
}

function bar(config: ConfigFixed /* replace from Config since TypeScript 2.0.0 */) {
    let data = fs.readFileSync(config.filePath, "utf8");
    config.verbose && console.log(data);
}

or

function withDefaultValue(config: Config = {}): ConfigFixed {
    config.filePath = config.filePath || "settings.json";
    config.verbose = config.verbose || false;

    return config;
}

function buzz(config: Config = {}) {
    // I can add below line without constraint.
    config = withDefaultValue(config);
    // I want to `config` value be `ConfigFixed` type by Control flow based type analysis.
    config.filePath;
}

Off topic.

function withDefaultValue2(config: Config = {}): ConfigFixed {
    // valid. cool!
    return Object.assign(config, {
        filePath: "settings.json",
        verbose: false,
    });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixedSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions