microsoft / microsoft/TypeScript

Proposal: allow variance annotations on input positions

未关闭
#62,639 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Awaiting More Feedback Suggestion
主要语言
Go
星标
111k
派生
14.3k
平均合并
2 天 4 小时
30 天内合并 PR
132

描述

⭐ Suggestion

I would like the in and out type modifiers to be able to applied to a generic type when it is being instantiated.

This would function by expanding the type by eliminating fields that are in violation of the requested constraint.

This might be thought of as another form of anonymous type mapping.

For example the code that can currently be written as

interface BivariantSetLike {
    size: number;
}
interface CovariantSetLike<out T> extends BivariantSetLike {
    getAll: () => Iterable<T>;
}
interface ContravariantSetLike<in T> extends BivariantSetLike {
    add: (key: T) => void;
}
interface SetLike<in out T>
    extends CovariantSetLike<T>,
        ContravariantSetLike<T>,
        BivariantSetLike {
    constrain: (key: T) => T | undefined
}

declare const dogs: SetLike<Dog>;
const animals: CovariantSetLike<Animal> = dogs;
const poodles: ContravariantSetLike<Poodle> = dogs;
const countable: BivariantSetLike = dogs;

Could instead be written as

interface SetLike<in out T> {
    size: number;
    getAll: () => Iterable<T>;
    add: (key: T) => void;
    constrain: (key: T) => T | undefined;
}

declare const dogs: SetLike<Dog>;
const animals: SetLike<-in Animal> = dogs;
const poodles: SetLike<-out Poodle> = dogs;
const countable: SetLike<-in -out void> = dogs;

I'm not opposed to allowing the non-negated forms to be used in type instantiations, but in line with the existing pattern that in and out already don't impose variance restrictions on otherwise variant code: I think the positive forms, if they are even syntactically allowed, should always no-op. So MyType<T> == MyType<in T> == MyType<out T> == MyType<in out T>

readonly and writeonly

field: -in T -> readonly field: T
field: -out T -> set field(value: T)
readonly field: -in T -> readonly field: T
readonly field: -out T -> (field is skipped)
set field(value: -in T) -> (field is skipped)
set field(value: -out T) -> set field(value: T)

This would break for an index signature type like {[n: number]: T} for -out T, because there is no syntax to describe a writeonly [n: number].
Perhaps, instead of simplifying types to remove the -in ReifiedT, it is just legal to use the -in and -out modifiers anywhere a type is legal inside of an object type, and it just impacts the semantics of the type.
If this were the case, it would be legal to write something like {x: -in number} as an alias for {readonly x: number}. I'm not particularly fond of this option, but it does provide an elegant answer for lacking writeonly.

Strict Methods

TypeScript treats methods and functions differently when it comes to variance (assuming --strictFunctionTypes, which is table stakes for any use of the in out modifiers anyway). I think the special treatment of methods should be ignored when using this new syntax, as it largely defeats the purpose. So WritableFunction and WritableMethod will remain distinct, but T1 and T2 ought to be be identical:

interface WritableFunction<T> {
    write: (value: T) => void;
}
interface WritableMethod<T> {
    write(value: T): void;
}

type T1 = WritableFunction<-in number>;
type T2 = WritableMethod<-in number>;

The alternative is to make a --strictMethodTypes flag that enables method type checking everywhere.
This proposal's syntax would, I believe, allow for things like Array to be mostly usable, despite their non-variance.

🔍 Search Terms

Variance covariance contravariance bivariance in out input

✅ Viability Checklist

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

该 issue 没有指明任何实现文件或测试。首先定位 TypeScript 的类型检查和泛型实例化路径,然后将它们与 variance、readonly/writeonly、index-signature 和 strict-method 示例进行比较。完成的要求是就各个替代方案的语义达成一致,并由编译器测试覆盖所提议的语法。

由索引模型根据 Issue 内容生成。

评估

技术栈
typescript
领域
compilers
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
基本清楚
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。