Non-nullable types

This PR implements support for null- and undefined-aware types and strict null checking that can be enabled with a new --strictNullChecks compiler switch. For context on this topic, see discussion in #185.
Null- and undefined-aware types
TypeScript has two special types, Null and Undefined, that have the values null and undefined respectively. Previously it was not possible to explicitly name these types, but null and undefined may now be used as type names regardless of type checking mode.
The type checker previously considered null and undefined assignable to anything. Effectively, null and undefined were valid values of every type and it wasn't possible to specifically exclude them (and therefore not possible to detect erroneous use of them). This changes in the new strict null checking mode.
In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any (the one exception being that undefined is also assignable to void). So, whereas T and T | undefined are considered synonymous in regular type checking mode (because undefined is considered a subtype of any T), they are different types in strict type checking mode, and only T | undefined permits undefined values. The same is true for the relationship of T to T | null.
// Compiled with --strictNullChecks
let x: number;
let y: number | undefined;
let z: number | null | undefined;
x = 1;  // Ok
y = 1;  // Ok
z = 1;  // Ok
x = undefined;  // Error
y = undefined;  // Ok
z = undefined;  // Ok
x = null;  // Error
y = null;  // Error
z = null;  // Ok
x = y;  // Error
x = z;  // Error
y = x;  // Ok
y = z;  // Error
z = x;  // Ok
z = y;  // Ok

Assigned-before-use checking
In strict null checking mode the compiler requires every reference to a local variable of a type that doesn't include undefined to be lexically preceded by at least one assignment to that variable. For example:
// Compiled with --strictNullChecks
let x: number;
let y: number | null;
let z: number | undefined;
x;  // Error, reference not preceded by assignment
y;  // Error, reference not preceded by assignment
z;  // Ok
x = 1;
y = null;
x;  // Ok
y;  // Ok

The analysis simply checks that an initializer or an assignment exists somewhere before each reference. It doesn't check that all possible code paths assign a value. For example, a missing assignment in one branch of an if statement is currently not flagged. We may implement more complete definite assignment analysis at some point, but it is beyond the scope of this PR. (Note that any solution we implement is unlikely to ever find all issues because it is in practice impossible to exhaustively reason about the effects of references to local variables from nested functions.)
Optional parameters and properties
Optional parameters and properties automatically have undefined added to their types, even when their type annotations don't specifically include undefined. For example, the following two types are identical:
// Compiled with --strictNullChecks
type T1 = (x?: number) => string;              // x has type number | undefined
type T2 = (x?: number | undefined) => string;  // x has type number | undefined

Non-null and non-undefined type guards
A property access or a function call produces a compile-time error if the object or function is of a type that includes null or undefined. However, type guards are extended to support non-null and non-undefined checks. For example:
// Compiled with --strictNullChecks
declare function f(x: number): string;
let x: number | null | undefined;
if (x) {
    f(x);  // Ok, type of x is number here
}
else {
    f(x);  // Error, type of x is number? here
}
let a = x != null ? f(x) : "";  // Type of a is string
let b = x && f(x);  // Type of b is string?

Non-null and non-undefined type guards may use the ==, !=, ===, or !== operator to compare to null or undefined, as in x != null or x === undefined. The effects on subject variable types accurately reflect JavaScript semantics (e.g. double-equals operators check for both values no matter which one is specified whereas triple-equals only checks for the specified value).
Dotted names in type guards
Type guards previously only supported checking local variables and parameters. Type guards now support checking "dotted names" consisting of a variable or parameter name followed one or more property accesses. For example:
interface Options {
    location?: {
        x?: number;
        y?: number;
    };
}

function foo(options?: Options) {
    if (options && options.location && options.location.x) {
        const x = options.location.x;  // Type of x is number
    }
}

Type guards for dotted names also work with user defined type guard functions and the typeof and instanceof operators and do not depend on the --strictNullChecks compiler option.
A type guard for a dotted name has no effect if any part of the dotted name is the target of an assignment within the guarded code. For example, a type guard for x.y.z will have no effect if the guarded code contains any assignments to x, x.y, or x.y.z.
Expression operators
Expression operators permit operand types to include null and/or undefined but always produce values of non-null and non-undefined types.
// Compiled with --strictNullChecks
function sum(a: number | null, b: number | null) {
    return a + b;  // Produces value of type number
}

The && operator adds null and/or undefined to the type of the right operand depending on which are present in the type of the left operand, and the || operator removes both null and undefined from the type of the left operand in the resulting union type.
// Compiled with --strictNullChecks
interface Entity {
    name: string;
}
let x: Entity | null;
let s = x && x.name;  // s is of type string | null
let y = x || { name: "test" };  // y is of type Entity

Type widening
The null and undefined types are not widened to any in strict null checking mode.
let z = null;  // Type of z is null

In regular type checking mode the inferred type of z is any because of widening, but in strict null checking mode the inferred type of z is null (and therefore, absent a type annotation, null is the only possible value for z).
Non-null assertion operator
A new ! postfix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms <T>x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.
// Compiled with --strictNullChecks
function validateEntity(e: Entity?) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e: Entity?) {
    validateEntity(e);
    let s = e!.name;  // Assert that e is non-null and access name
}

Compatibility
The new features are designed such that they can be used in both strict null checking mode and regular type checking mode. In particular, the null and undefined types are automatically erased from union types in regular type checking mode (because they are subtypes of all other types), and the ! non-null assertion expression operator is permitted but has no effect in regular type checking mode. Thus, declaration files that are updated to use null- and undefined-aware types can still be used in regular type checking mode for backwards compatiblity.
In practical terms, strict null checking mode requires that all files in a compilation are null- and undefined-aware. We are contemplating a pragma of some form that can be added to declaration files such that the compiler can verify that all referenced declaration files are null- and undefined-aware in a compilation that uses strict null checking.
Remaining work

Tests.
Update lib.d.ts to use null- and undefined-aware types.
Pragma to indicate declaration file has been updated to use null- and undefined-aware types.

This compiles without error under --strictnullchecks
let x: string;
x.substr(10);

while the equivalent
let x: string = undefined;
x.substr(10);

does not

@RyanCavanaugh Yup, that's the definite assignment analysis work item I've got listed in the remaining work section.

Note: We use postfix notation for the ? operator to avoid ambiguities in types
like string?[] and string[]?. We may consider also supporting prefix notation similar to
the Flow type checker.

If Flow and TypeScript can agree on syntax for this and thereby enable code to be parsed with either TypeScript or Babel that would be very helpful for projects wishing to try one or the other.

:+1: to this work

type guards are extended to support non-null checks.

Can I confirm the following is also a valid type guard on x?
// Compiled with --strictNullChecks
interface Entity {
    name: string;
}
let x: Entity?;

if (x != undefined) {
    // x is of type Entity
    // guaranteed runtime safe use of x
}

Expression operators permit the operands to be both nullable and non-nullable and always produce values of non-nullable types.

Please can you explain the rationale behind this?
I would have thought the following a more intuitive interpretation:
// Compiled with --strictNullChecks
function sum(a: number?, b: number?, c: number, d: number) {
    console.log(a + b);  // error
    console.log(a + c);  // error
    console.log(c + d);  // OK
}

A new ! postfix expression operator may be used to assert that its operand is non-nullable in contexts where the type checker is unable to conclude that fact.

Given the support you describe with type guards, can you explain why this is operator is necessary?

:+1: very nice to see this!
There was some discussion in other issues about the if(x) style typeguards WRT falsy values.
For example:
let x: number? = 0;
let y: string? = '';
let z: boolean? = false;

In particular, boolean? guarding with if(z) feels pretty bad, since false is one of the two legitimate values. The other are unfortunate but not terrible.
It would be nice to have a guard work on x != null to get around this issue.

@myitcv Yes, x != undefined will work as a non-null guard (right now it only works with x != null but I will fix that).
The rationale for the expression operators is that they actually have well defined semantics for the null and undefined values. Certainly we want to support nullable values for the comparison operators, but I can see being more restrictive for the arithmetic operators. Still, not sure it merits the extra complexity.
The postfix ! assertion operator is useful in cases where the type checker can't conclude that a value is non-null but you know it to be true because of program logic. My description of the PR above gives an example of such a case.
@tejacques An x != null type guard already works.

Ah yes I see the commit now -- thanks @ahejlsberg! Very excited about this and I'll be testing it out extensively over the weekend.

Is this feature just a sugared view on a | void that has been used meanwhile?

Somewhat related to @myitcv's question, do ProperyAccess and ElementAccess expressions permit their left operand types to be nullable? I couldn't find an error for this in the review, but figured it is likely disallowed by virtue of the union type representation.

@JsonFreeman (Hi, Jason!) Property and element accesses are disallowed when the left operand is nullable (as you say, because of the union type representation).

Thanks Anders! I'm happy to see this feature come together so well - I think it's a big step for the language :)

Definite assignment analysis for non-nullable variables and properties in classes.

@ahejlsberg I think #6959 can be used for this (if it will be merged), as my PR can already narrow types based on assignments:
let x: string | number;
x = 42;
// x: number

That can also be used to narrow T? to T. In general, I think that those two features would be a nice addition to each other.

As described I don't think this will work very well with default parameters. I've found it's quite common to pass undefined as an argument to a function with default parameter values, either explicitly as undefined, or (more common) as the possibly-undefined value of an optional parameter. This proposal seems to break that:
function makeRange(min = 'A', max = 'Z') { /* ... */ }

makeRange(undefined, 'M'); // Safe - use default first param while specifying second
// Error: "Argument of type 'undefined' is not assignable to parameter of type 'string'."

makeRange(null, 'M'); // Bad, should still be an error

function makeBRange(max?: string) {
    return makeRange('B', max); // Safe - if max not specified, use default
    // Error: "Argument of type 'string?' is not assignable to parameter of type 'string'."
    // This pattern is very common in constructor super() calls
}

I would suggest that:

a default parameter of type T should have a signature type of T|undefined
an optional parameter declared of type T should have a type of T|undefined rather than T|null|undefined. (To allow it to be null as well, add the second question mark)

@jeffreymorlan I see what you're saying, but it would require treating null and undefined as distinct and incompatible types and users would have to reason about the subtle distinctions between T, T | undefined, T | null, and T? (which would be the same as T | null | undefined). Currently there's just T and T? which is a lot simpler. Not an easy choice to make.

I am actually surprised that a parameter with a default initializer is not nullable. Shouldn't it be treated just like a question token?

@JsonFreeman We currently infer a nullable type for a parameter only when the default value is nullable. This means you can't explicitly pass undefined (which is what @jeffreymorlan doesn't like), but it also means that within the function you don't have to use null guards. An alternate approach would be to type the parameter as T | undefined in the signature, but just T within the function. This would allow you to explicitly pass undefined but wouldn't force you to use type guards within the function.

Thanks @ahejlsberg. I do think it might make sense in this case to distinguish between the signature's parameter and the value declaration in the function's scope. The fact is that the former is allowed to be undefined, but the latter won't be. I think the same could be said of destructuring elements with default values, where the RHS value can be nullable, but the binding name introduce a value declaration that's not nullable.

An alternate approach would be to type the parameter as T | undefined in the signature, but just T within the function.

For what it's worth, this is how it works in Flow.

I have a few question regarding nullable members. Would like if allowed vs. not allowed can be answered below :rose:
interface Foo1 {
	foo?: number;
}
let foo1:Foo1;

interface Foo2 {
	foo: number?;
}
let foo2:Foo2;

foo1 = foo2; // allowed?
foo2 = foo1; // allowed?

foo1 = {}; // This is already allowed
foo2 = {}; // allowed?

@basarat running with the current branch I get (lines inlined):
foo2 = foo1; // allowed?
../../throwaway/clipboard.ts(13,1): error TS2322: Type 'Foo1' is not assignable to type 'Foo2'.
  Property 'foo' is optional in type 'Foo1' but required in type 'Foo2'.

foo2 = {}; // allowed?
../../throwaway/clipboard.ts(16,1): error TS2322: Type '{}' is not assignable to type 'Foo2'.
  Property 'foo' is missing in type '{}'.

How does subtyping work w.r.t. nullables? Are object types property-wise invariant to account for aliasing hazards?
interface A {
  foo: string;
}
interface B {
  foo: string?;
}

let a: A = { foo: "foo" };
let b: B = a; // is this allowed?
b.foo = null; // because this would be bad, right?

Are object types property-wise invariant to account for aliasing hazards?

In general TS treats all types as covariant, which is also why it allows you to assign an Array<Cat> to an Array<Animal> and then assign a Dog to animals[0]

Latest commits add support for "dotted names" in type guards. The description of the PR has been updated with a new section to describe this feature.

@ahejlsberg that's awesome!
What's about type inference for generics? Some thoughts come to my mind:
interface A { a: number; }
declare function foo<T extends A>(p: T?): void;
declare function boo<T extends A?>(p: T?): void;

let a: A;
let na: A?;

foo(na); // is 'T' = 'A' ?
boo(na); // is 'T' = 'A?' ? is 'p' of type 'A??' ? is it assignable from 'A?' ?
foo(a); // is 'T' = 'A' ?
boo(a); // is 'T' = 'A?' ? is 'p' of type 'A??' ? is it assignable from 'A' ?
foo<A?>(a); // is constraint not met?

@Igorbek Nullable types are just syntactic sugar for union types that include type of null/undefined. So, type inference works just like type inference for union types. In each of your first four examples the inferred type for T is A (because when inferring from either A to T? or A? to T?, we infer A for T). An error is reported in the last example because the explicitly specified type doesn't satisfy the constraint (A? isn't assignable to A).
Note that constraints have no effect on type inference, they aren't checked until after type inference is complete. Also, since a nullable type is just a union type, it simply isn't possible to have a type A?? (because for any two types X | Y is the same as X | Y | Y).

Thank you, it makes sense :+1:

Big :+1:
In the explanation for this feature I see this
// Compiled with --strictNullChecks
type T1 = (x?: number) => string;   // x has type number?
type T2 = (x?: number?) => string;  // x has type number?

Is it fair to say
type T3 = (x: number?) => string;  // x has type number?

too?   (that is, x is an optional parameter so if not specified it's undefined)

@IanYates I don't think that should be the case. If the author has listed something as nullable and not optional, they probably want users to explicitly specify the parameter (or they didn't know better).

@IanYates agree with Daniel. x: number? doesn't make x optional, just makes it nullable. This is similar to the question I had https://github.com/Microsoft/TypeScript/pull/7140#issuecomment-188486812 a member doesn't become optional just becomes nullable :rose:

Thanks for the clarification.  I should've actually looked at my own Typescript code before writing as I see what I actually wanted to ask was actually T1 and I was confusing it with T3 (too much mixing of C# and Typescript on the weekend).  But good to know anyway and what you've said makes makes good sense.

Latest commit implements simple assigned-before-use checking that requires a reference to a local variable of a non-nullable type to be lexically preceded by at least one assignment to that variable. For example:
let x: number;
x;  // Error, reference not preceded by assignment
x = 1;
x;  // Ok

The analysis simply checks that an initializer or an assignment exists somewhere before each reference. It doesn't check that all possible code paths assign a value. For example, a missing assignment in one branch of an if statement is currently not flagged. We may implement more complete definite assignment analysis at some point, but it is beyond the scope of this PR. (Note that any solution we implement is unlikely to ever find all issues because it is in practice impossible to exhaustively reason about the effects of references to local variables from nested functions.)

Awesome.
re: dotted names, does it work for union types like https://github.com/Microsoft/TypeScript/issues/1260 ?

Very very cool.  Is there any proposed facility to opt into --strictNullChecks on a more granular level.  Putting it on at the entire compilation level would mean a lot of up front work to convert some existing code over to use this.  If i could do this at a smaller level (say the file level), that would be super useful.
Thoughts?

@danquirk It doesn't include the property based type guards suggested in #1260, but we could discuss reviving that idea.
@CyrusNajmabadi Yes, I thought a more granular level, but for reasons of simplicity I prefer a project wide switch. The core issue is that I don't see how it is possible to support file level opt-in without introducing a whole new kind of type. In a granular world it might be easy to change what syntax means in a particular file (i.e. string means "string new old semantics" or "string with new semantics" string depending on file context), but the type checker would need to track the distinction in the types themselves as there's no notion of "the current file" when checking types. Unfortunately, the semantics (assignability, allowed operations, etc.) of a particular type T under the old rules matches neither T nor T? under the --strictNullChecks rules, so we'd have to introduce a new internal representation (say T~) that means "T with old semantics" and then propagate that everywhere in the type system. This creates quite a lot of complexity and is not at all intuitive to reason about. My conclusion is that we're better off not going there.

I'm just wondering if index expression is always considered as nullable?
const s: string[];
function at(index: number): string {
    return s[index]; // error nullable is not assignable to non-nullable
}

Because an arbitrary index value can yield a void type.

@tinganho Indexing simply produces a value of the type declared in the matching index signature. Even if it is technically more correct, it would simply be too painful if we automatically added undefined to the type of every indexing operation. For example, every array element access would have to be accompanied by a non-null guard or a ! assertion. I think that would become hugely irritating.

It's hard to say. I could see it becoming very irritating in some cases, but potentially helpful in others. I would be fairly confident that it would at least catch some bugs in user code. But I agree that it's a tough call, and I think the current approach is reasonable.

I others cases (where taking a value at index implies possibility hitting
undefined) can't you just declare it number?[] rather than number[]?
On Sat, Mar 5, 2016 at 3:02 PM, Jason Freeman<EMAIL_ADDRESS>wrote:

It's hard to say. I could see it becoming very irritating in some cases,
but potentially helpful in others. I would be fairly confident that it
would at least catch some bugs in user code. But I agree that it's a
tough call, and I think the current approach is reasonable.
—
Reply to this email directly or view it on GitHub
https://github.com/Microsoft/TypeScript/pull/7140#issuecomment-192720644
.

--
Aleksey Bykov

I others cases (where taking a value at index implies a possibility of hitting
undefined) can't you just declare it number?[] rather than number[]?

This is probably too complicated, but there are a few cases where you can statically know an array access to have a defined result. For example...
const array = ["hello","world"]; // string[]
const nullableArray = ["hello", null]; // string?[]
for (const i=0; i<array.length; i++) {
  console.log(array[i].toUpperCase());
}

In this case, i cannot possibly be any value other than 0-array.length. It gets more complicated if i is defined with let or var though, since it might have been modified elsewhere in the scope.

Just pushed a new batch of commits. Core theme is separation of null and undefined as distinct types that are not assignable to each other. The initial implementation of this PR conflated the two, but that precluded programming in a style that uses only one of the two (for example, the TypeScript compiler doesn't use null at all). Changes include:

Make null and undefined distinct types and allow them to be used as type names.
The type T? is exactly the same as T | null | undefined.
No widening of null and undefined in strict null checking mode.
Best common supertype computed using non-nullable form of types.
Introduce new comparable relation (see #5517) that is used for equality operators and type assertions. A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T. There was already a need for this new relation and nullable types add more justification. For example, given types A and B where one is a subtype of the other, it isn't possible to compare A to B? or A? to B without this change.
Optional parameters and properties now have undefined (but not null) added to their type. For example x?: T automatically becomes x?: T | undefined.
An expressionless return statement is treated as return undefined for type checking purposes.
undefined is included in the inferred type of a function that has expressionless return statements and/or a reachable end point (which implies returning undefined).
It is an error to have a reachable end point in a function with a type annotation that doesn't include undefined.
Type guards using ==, !=, ===, and !== to compare to null or undefined now accurately reflect JavaScript semantics (e.g. double-equals operators check for both values no matter which one is specified whereas triple-equals only checks for the specified value).
Improved type relationship error reporting for nullable types.
Several smaller issues fixed.

I will update the description of the PR accordingly as soon as possible.

About the arithmetic operators being exempt from null checks - seems like a significantly big hole / footgun.
Its borderline acceptable for addition and subtraction as it defaults to the identity element (so a noop) but I'm pretty sure multiplication and especially division will cause some significant bugs (division is bound to produce unwanted NaNs :)
Other than that, huge, huge +1 from me.

Thumbs up! I thought I would never see this happening. Thank you for choosing to model the JavaScript type system the way it is.

@ahejlsberg, what is going to happen with the void type? There is no match to it in JavaScript. It's hard to see what it will be modeling. An alias to the Undefined type in a position of a return type of a function? As far as I remember according to the current spec void doesn't have  value but can be assigned null or undefined which are now distinct referrable types. In this perspective the void type looks more like an alias to Null | Undefined. I suspect that it can also remain an outlaw type that has its very own semantics that doesn't match anything in JavaScript, but in view of what you just said eliminating it altogether looks like a better alternative considering other changes that seem breaking anyway.

@dallonf consider
const array = ["hello","world"]; // string[]
const nullableArray = ["hello", null]; // string?[]
for (const i=0; i<array.length; i++) {
  ahChooExcuseMe();
  console.log(array[i].toUpperCase());
}
function ahChooExcuseMe () {
   if (Date().getTime() ÷ 2 > 0) {
      array.pop();
      array.pop();
   }
}

point is, array is mutable, you can only reliably reason about static (guaranteed immutable) values doing static analysis

@spion Yes, I think you have a point about the arithmetic operators. They probably shouldn't allow nullable types.
@aleksey-bykov In strict null checking mode, void is assignable to and from only itself and the any type. The null and undefined types are specifically not assignable to void. The allows us to think of void functions as not returning anything (which I think is the right intuition), as opposed to functions that return undefined. In the latter view, the result of a void function would be assignable to any nullable type. That makes no sense in my opinion.

@ahejlsberg, so

function with a return type void isn't allowed to have an expression in its return statements, is it?

next question, would we still able to get a value of type void, say:

const nothing:void = (function  ():void {})();

for the sake of better maintainability and inference experience we are not going to have to support 2 sets of signatures: with and without return type like Action and Func delegates in C#, are we?

@aleksey-bykov

a function with a return type void won't be allowed to have an expression in its return statements, will it? or will it still be ok to return a value of type void or any from a void-function?

A void function is permitted to return expressions of type void or any. And it is of course allowed to have return statements with no expressions and an implied return at the end.

we will still be able to get a value of type void, won't we?

Sure. You could also just write <void><any>undefined.

for the sake of better maintainability and inference experience we are not going to have to support 2 sets of signatures: with and without return type like Action and Func delegates in C#, are we?

No. The difference here is that TypeScript's void is a full fledged type whereas C#'s void is just a keyword to indicate a function with no return value.

A function with no return statement does return undefined. As far as I can tell, void and undefined are the same type.

@samwgoldman Yes, undefined should obviously be assignable to void. However, you don't want the opposite to be true and it still makes sense to have two distinct types such that void values aren't unintentionally assigned to variables or parameters with types that include undefined. For example, you wouldn't want to be able to pass the result of a void returning function to another function with an optional parameter.

For example, you wouldn't want to be able to pass the result of a void returning function to another function with an optional parameter.

Why not? It's fine at runtime and presumably the function handles the undefined case internally. I could certainly imagine a warning in this case, something like "void value uselessly passed to function" but it's a lint error, not a type error.

@samwgoldman Yes, passing a the result of a void function to a function that takes string | undefined would behave correctly (because the only value of void is undefined), but I don't think it would ever be the actual intent. For that reason I think it should be an actual type error and not just a linting error.

OK—agree to disagree. Thanks for taking the time to explain your reasoning.

The null and undefined types are specifically not assignable to void.

A void function is permitted to return expressions of type void or any. And it is of course allowed to have return statements with no expressions and an implied return at the end.

An expressionless return statement is treated as return undefined for type checking purposes.
undefined is included in the inferred type of a function that has expressionless return statements and/or a reachable end point (which implies returning undefined)

@ahejlsberg I think I got a little bit trouble understand the above cited statements. Though I think I understand your intention. void will be treated as a function which is not returning anything.
Isn't it slightly better to have expressionless return statements(i.e. return;) to return void type instead of undefined type. And endpoints with implied return statements also returning void type? Then people will not be confused with undefined/null is or is not assignable to void.
Here is some examples of it:
function returnNullableString(): string? {
    if (Date.now() % 2 > 0) {
         // error, void type is not assignable to string?
    }
    else {
        return 'hello world';
    }
}

function returnNullableString(): string? {
    if (Date.now() % 2 > 0) {
        return undefined; // no error
    }
    else {
        return 'hello world';
    }
}

function returnNullableString(): void {
    return undefined; // error, undefined is not assignable to void
}

function returnNullableString(): void {
    // no error, void is assignable to void
}

function returnNullableString(): void {
    return; // no error, void is assignable to void
}

@tinganho The --noImplicitReturns compiler switch already handles your first example:
function returnNullableString(): string? {
    if (Date.now() % 2 > 0) {
         // Missing return here causes error with --noImplicitReturns switch
    }
    else {
        return 'hello world';
    }
}

In the second example, I really don't think there is anything wrong with permitting return undefined in a void function. After all, undefined is assignable to void (and is actually the value returned by a void function).

For those following this thread; I have filed https://github.com/Microsoft/TypeScript/issues/7426 to get input on what T? should refer to. would love to hear your input.

I tried this out a bit today. A few suggestions/possible bugs:

Passing an undefined value to a default parameter is still an error - should be allowed:

function f(a = 'foo') {}
f(undefined); // Argument of type 'undefined' is not assignable to parameter of type 'string'.

Would be nice if dotted-name type guards allowed this at the beginning, to allow code like this.x && this.x.f() - I write code like that very often (probably even more than with a local variable at the beginning)
I think indexing nullable/undefinedable (or void?) types should be an error, since any property access on null/undefined throws an exception. Right now an error is only given with --implicitAny:

var a: number[] = [42];
var b: number[]? = null;
var a2 = a[0]; // allowed
var b2 = b[0]; // allowed, b2 implicitly has "any" type

The definite assignment analysis doesn't recognize when a variable is assigned in all cases of a switch statement:

var flag: boolean;
switch (0) {
    case 0: flag = false; break;
    default: flag = true; break;
}
console.log(flag); // Error: "Variable 'flag' is used before being assigned"

Latest commits improve checking of parameters and binding elements with default values.
When an optional parameter specifies a default value, we add undefined to the type of the parameter in the function signature, but not within the function body:
function len(s: string = "") {
    return s.length;  // Type of s doesn't include undefined
}

let a = len();  // Same as passing undefined
let b = len(undefined);  // Signature permits undefined
let c = len("hello");

When a binding element specifies a default value and when the type of that default value doesn't include undefined, we remove undefined from the type of the binding element:
let p: { x?: number, y?: number } = {};
let { x = 0, y } = p;
x;  // number
y;  // number | undefined
let o: { p?: { a?: number, b?: number } } = {}
let { p: { a = 0, b } = { a: 0, b: 0 } } = o;
a;  // number
b;  // number | undefined

So glad this is happening :sparkles:
I had my own prototype of this so I'm curious about the hard questions I encountered.
(1) undefined vs null is the elephant in the room. I'll go to #7426 for that.
(2) Since undefined is so pervasive in JS I guess the design is to cover "normal" cases and have some holes in the safety net? For instance, any array access can produce undefined but if you try to cover that the language will become unusable... ! everywhere.
In the same vein: what are you doing for class fields?
class X {
  notnull: VeryComplexClass;   // Do I have to assign a default value to all fields?

  constructor(init: VeryComplexClass) {
    // Can I (do I have to?) init in ctor?
    // What if this is a derived class with a virtual call in `super()` ?
  }

  // Or am I on my own to make sure it gets initialized at some reasonable point?
}

(3) The show stopper for my prototype was trying to make a per-file indicator whether code source is null-aware or not. This seemed key for the backward compatibility story but it was really hard because I would need to annotate each type instance to indicate which null-rules it adhered to. That's where I gave up. I see you choose to not support "mixed" compilation and I can clearly see why.
If I understood correctly, even a brand new project would need to only use .d.ts that have been updated with nullability? That's going to be painful at beginning. I can imagine the most "popular" libraries quickly updated, but then the rest... it will be hard. Even today some "popular" libraries have so-so definitions, but patching them is no too much work.
Updating a large definition is a lot of work, though. And if a single library you use is not updated: either you give up on null checks or (more probably) you give up on that library definitions :disappointed:
(4) How do you envision the standard APIs that use undefined to signify unavailable cases? Like out of bounds array[i] returns undefined, there are lots of APIs like Array.find(), Map.get(), etc. that return undefined if the condition/index does not match.
Do you think you will declare them Array<T>.find(): T | undefined, so that we will need to ! if we are sure the value was found?

@jods4

For instance, any array access can produce undefined but if you try to cover that the language will become unusable... ! everywhere.

Exactly, see previous discussion here.

In the same vein: what are you doing for class fields?

The thinking is that we'll ensure all non-nullable properties declared in a class are assigned in the constructor. This is not currently implemented.

If I understood correctly, even a brand new project would need to only use .d.ts that have been updated with nullability?

Old declaration files will compile in --strictNullChecks mode, but they likely won't reflect the correct semantics (for example because functions will always appear to return non-null and non-undefined values). So yes, all referenced declaration files must be nullable-aware before you can expect to meaningfully use the feature. The good news is that, once updated, declaration files can be used in both modes with no changes.

Do you think you will declare them Array.find(): T | undefined, so that we will need to ! if we are sure the value was found?

I will depend on the particular API. Some APIs return undefined only when they're used incorrectly (similar to out-of-bounds indexing) and for those you likely don't want to include undefined in the type. Others return undefined as a possible value for correct uses of the API and for those you'll want to include it. In some cases this will be a judgement call by the declaration file author.

I will depend on the particular API. Some APIs return undefined only when they're used incorrectly (similar to out-of-bounds indexing) and for those you likely don't want to include undefined in the type. Others return undefined as a possible value for correct uses of the API and for those you'll want to include it. In some cases this will be a judgement call by the declaration file author.

This is going to be debatable indeed, except for the most obvious "incorrect use" APIs. For instance do you think Map.get() on a non-existing key is API misuse?
I would lean toward including undefined when in doubt, because ! makes things not too hard:
let x = Map.get("x")!; // yes I know it's there
And somehow, ! serves as a reminder that I made a non-verifiable assumption there. I kinda like it, it makes me think of a warning sign.

I would like to take out of the noisy #7426 discussion over the meaning of T? one comment that I think is worth discussing separately and before the next release.
At least four people have voiced their concern that introducing let x?: T might be a mistake.
(1) it is not very logical.
Parameters and interface members make sense. ? means that whatever is on the left is optional. Although they modify the underlying type by adding undefined, they apply to the identifier and are not identical to the equivalent declaration without ?.
f(x?: number|undefined) has a meaning and is different from f(x: number|undefined). The same can be said for interface members.
let x?: T on the other hand makes no sense. x is not optional at all, it is a declared variable and if you try to redeclare it you'll get an error:
let x?: number;
let x: any; // what did you think?

In fact this is nothing more than syntactical sugar for let x: T|undefined, so there's no reason the mark is not on the type itself...
Speaking of consistency, if it's allowed on parameters, interface members and variables, there's just no reason you don't allow it everywhere... which would look silly.
In addition to that, this will not play nice with a possible future T?. Should we settle on T? = T|undefined this syntax would simply not be required at all. Should we settle on T? = T|null this will be quite confusing to explain.
(2) About T? you said that you want more time to bake syntactical sugar (if any), so please don't add syntactical sugar yet!. Because let x? is just T? = T | undefined in disguise.
There are several adverse effects to adding one and not the other.
Most notably, you are setting up a self-fulfilling prophecy. I can already foresee the Q/A on StackOverflow:

So how do I use those nullable types?

Easy, just use let x?, that also works on parameters!
Shouldn't you use null though?
Are you high? The keystrokes!

And then in one month when you look at null usage, you'll say "see: not many people use null anyway, we were right all along!".
Please wait until the discussion about undefined vs null settles down before hastily introducing any syntactical sugar!
The type checker is a great improvement, let's see how it plays out. Maybe you don't even need such sugar at all.

Latest commit removes the T? notation per conclusion from discussion in #7426. We may add it back at some point in the future if there is ever consensus as to what it should mean.

I've read this page again but couldn't find information about the behaviour of any?
Because any could be null or undefined, is this going to be an error?
(<any>x).something()
Or does any disable all type checks including the new strict nulls?
My first intuition would be that any is opting out of typing so I should be allowed to do anything without compiler errors.
If you choose the other way, will there be a non-null any: let x: any! ?

@jods4 The behavior of any doesn't change. You can assign anything to an any and it effectively disables both strict and regular type checking.

@jods4
You mentioned:

let x?: T on the other hand makes no sense. x is not optional at all, it is a declared variable and if you try to redeclare it you'll get an error.

First, I'm not sure what you exactly meant because re-declaring am optional function argument would also yield an error:
function func( x?: number) {
  let x: string; // <-- Error: duplicate identifier
}

In any case, I am one of those people who actually never felt any problem with the let x?: T notation and even proposed and tried to promote it as a valid candidate. I can accept it is to some degree an analogy and does not represent a "complete" form of equivalence with the existing call signature and interface notation.
We need to separate two different scenarios where a value passed to a property or call signature argument having x?: T may be accepted, here's a basic example scenario:
function func(a: string, x?: number) {
...
}

interface MyInterface {
  a: string;
  x?: number;
}

The two main scenarios are:
(1). A value for x is not provided at all thus x is implicitly undefined. E.g:
func("hey");
let obj: MyInterface = { a: string }

(2). A value for x is provided but set to undefined had thus x is explicitly undefined. E.g.:
func("hey", undefined);
let obj: MyInterface = { a: string, x: undefined }

In terms of program execution, there is very little difference between these two cases. The only places a difference may surface is when enumerating function arguments such as with the arguments object or in the case of object, enumerating over object properties with for..in or Object.keys etc. where the property would appear but its value would be explicitly undefined. Other than that, the semantics are exactly the same.
It makes sense for me that x?: T notation should include cases where the value was explicitly passed as undefined, I mean, even in a stricter mode, thus having let x?: T, which as you mentioned would always be limited to the "explicitly undefined" semantics, which I feel is reasonable, and is a compromise I'm willing to take, if only to create consistency in the language and conservatively "recycle" the existing syntax in a way I feel is reasonably intuitive.
I'm actually quite surprised some people find this particular instance of the x?: T notation to be not as good or at least as reasonable as it may seem to me, and would be interested in hearing more of their views on the subject.

@malibuzios
I certainly did not lay out my ideas in the best possible way but I think you understood me well.
In itself the notation is not as much of an issue as the larger context of how the language presents itself to users, in particular newcomers.
Syntactical sugar such as let x?: T being shorthand for let x: T | undefined shapes the way the language will be used. Even more so without alternatives such as let x: T?.
A good language would naturally lead beginners towards the path of success and I'm not sure this is it.
Given that it is not decided yet what good usage of "nullables" is (see the heat in #7426); I think it's wise to wait before adding any syntax. Once added it can't be removed. Depending on how things go I think we could also consider alternatives to that syntax.
If you ask me, let x?: T is completely unnecessary and adds useless complexity to the language and confusion for beginners. But of course that's just me ;)

@jods4
I can understand different people may different views and if there is no consensus, then it is usually wiser to wait until a later stage, where perhaps more insight would be accumulated over real-world cases and usage.
I actually made a special effort to express my my opinion that T? would become less intuitive if the question mark is used to denote something else than optionality (i.e. denoting  T | null or T | null | undefined), which I felt may become a bit confusing for beginners, and would feel redundant if it was set to T | undefined - that's why I said I preferred nothing at all.
The let x?: T case was actually one of those places where I did not predict would become very controversial. It turns out it is, to some degree, and even some Microsoft members have expressed some doubts about it (see these design meeting notes under "optional members on new members"):

Variables are more of a questionable (pun intended) case - not entirely certain.

It seems like this would actually give you a case to say that your variable can be undefined and reflects that in the type.

Maybe I'm not seeing it broadly enough, but it seems there are many places in my code where when passing a value to a function which has an optional parameter, it would be natural to write something like:
function readSomeData(offset?: number)
  ..
}

function readMore() {
  let myOffset?: number;

  if (someConditionIsTrue())
    myOffset = getOffset(...);

  return readSomeData(myOffset)
}

I view the question mark in let myOffset?: number; as expressing the fact that myOffset may not be assigned at all (unlike the same notation in a class member, it is guranteed to exist - meaning in practice it is 'explicitly' set to undefined, despite the fact it may be never assigned). Think about it, even if it was, say, nulllable, it would still need to be assigned in order to have a value null. That's why this is mostly an analogy, not an exact parallel to the same notation in function parameters and interfaces/classes.
A roughly similar sort of symmetry is apparent in interfaces and implementing classes:
interface MyInterface {
  x?: number;
}

class MyClass implements MyInterface {
  x?: number;
}

@malibuzios I don't know. I find that T? conveys well the fact that the T value is optional. It's also convenient that it can be used everywhere a type is used (return values, generic parameters, etc.) -- what it should compile to seems highly controversial though.
Your readSomeData() example is correct but in practice I think optional parameters are most commonly omitted rather than explicitly passed as undefined.
In my opinion that makes your example an unusual case where the syntax let x: number | undefined would be acceptable. It seems too corner case to justify added complexity in the language.
Another point that I don't like with let x? is that when TS 2.0 comes out with strict nulls, the compiler will report non-definite assignements of variables. Like:
function f() {
  let x: number;
  if (blah) x = 3;
  // more blah
  return x; // <-- error: use of unassigned x variable.
}

This is a good thing and likely to catch bugs. Having let x? encourages you to opt out of this.

The implementation on this branch does not support getOrCreate() pattern yet.
The following logically correct program fails with a type error
class OutPendingBucket {
    elements: Array<number>;
    count: number;

    constructor(elems:Array<number>) {
        this.elements = elems;
        this.count = 0;
    }
}

class OutPending {
    buckets: { [id: string] : OutPendingBucket | undefined };
    emptyBucket: Array<number>;
    bucketSize: number;

    constructor() {
        this.buckets = Object.create(null);
        this.bucketSize = 1024;

        this.emptyBucket = [];
        for (var i = 0; i < this.bucketSize; i++) {
            this.emptyBucket.push(0);
        }
    }

    getOrCreateBucket(bucketStart:string) : OutPendingBucket {
        var bucket = this.buckets[bucketStart];
        if (!bucket) {
            var elems = this.emptyBucket.slice(0, this.emptyBucket.length);
            bucket = this.buckets[bucketStart] = new OutPendingBucket(elems);
        }

        return bucket;
    }
}

raynos at raynos-Dell-Precision-M3800  ~/projects/TypeScript on strictNullChecks*
$ node built/local/tsc.js --strictNullChecks test.ts
test.ts(34,16): error TS2322: Type 'OutPendingBucket | undefined' is not assignable to type 'OutPendingBucket'.
  Type 'undefined' is not assignable to type 'OutPendingBucket'.

It complains that bucket could be undefined even though I have a undefined check and re-assign it to a non-nullable type.
I think this shouldn't be too hard to implement but becomes harder if:

You are assigning to this.bucket = X and return this.bucket;
If you alias; aka this.bucket = X; var self = this; return self.bucket
If you do nested fields in data structures and nested aliases...

@Raynos
Your code requires flow analysis to determine that although bucket is nullable, it was definitely assigned a non-null value on every code path.
From what @ahejlsberg has written I think this is planned but not done yet.
In the meantime you can indicate to the compiler that you know bucket is not null by using:
return bucket!;

We've merged the PR with the work as it currently stands so people can experiment with it in the nightly builds.
NOTE: The --strictNullChecks compiler option should be considered experimental at this point.
We are working on a separate PR for control flow based type analysis (see #2388) that will allow us to better track definite assignment and type guards in all forms. The --strictNullChecks feature isn't really complete until that work is done.

@zhengbli Is there any plan to get https://github.com/Microsoft/TSJS-lib-generator to generate | null / | undefined automatically?

thanks @Arnavion, https://github.com/Microsoft/TSJS-lib-generator/issues/81.

Thanks! And for the non-generated .d.ts files, will you be taking PRs? Or are you already working on them?

core.d.ts and es6.d.ts at https://github.com/Microsoft/TypeScript/pull/7650

Zero values
When it comes to primitives (number, string, boolean) I had hoped this PR would introduce the concept of zero values, specifically 0 for number, "" for string and false for boolean. Consider:
let x: number;
console.log(x);

As it is, the above fails to compile (as documented) and requires that I do:
let x: number = 0;  // the type annotation is optional
console.log(x);

Introducing the concept of zero values would mean that the following:
let x: number;

gets transpiled to:
// JS result of transpilation
var x = 0;

making the original example valid again:
let x: number;
console.log(x);  // ok; outputs 0

Non-primitives
I'm really struggling to see the benefit of non-nullable types for any type that is not a primitive. Largely because at runtime all variables are in fact pointers (with both undefined and null being the uninitialised pointer values)
If we were to:

introduce the concept of a struct type
split the concept of an array into an array and slice (borrowing from the Go terminology)
adopt the same value semantics for structs and arrays as Go

then I would think differently, but that's an entirely different proposal to what is being discussed here. Indeed has such a proposal been discussed before?

@myitcv
Sorry but I strongly disagree with introducing "default" initialization of values.
(1) because using an uninitialized variable can easily be hiding a bug and "defaulting" to some arbitrary value like 0 is very likely not to fix it.
let x: number;
switch (size) {
  // forgot something...
//case "S": x = 1; break;
  case "M": x = 5; break;
  case "L": x = 10; break;
}
doSomethingWith(x);

I much prefer that the compiler gives me an error and tells me x might be uninitialized when calling doSomethingWith(x) rather than happily assuming I meant x = 0, which is likely to be incorrect.
Most statically typed languages require you to initialize your variables explicitely for this reason.
(2) because JS will behave differently from TS and this is unexpected.
In TS let x: number will compile to let x = 0
but plain JS let x actually means let x = undefined
(3) because TS can't provide a good default for non-nullable objects.
To what could possibly let x: ComplexType compile to?
This would be an inconsistency in the language, as JS doesn't make much difference between "references" and "values" like C# does...
(4) because there's no good default for union types, e.g. let x: number | boolean
(5) If you are trying to save keystrokes, it's even shorter to declare let x = 0 rather than let x: number!

I'm really struggling to see the benefit of non-nullable types for any type that is not a primitive

The benefit is huge! Guarantee at compile-time that your code is free of null-derefencing errors.
Catching stuff like that:
function fullname(p: Person) {
  // expects a non-null p, otherwise lastName.toUpperCase will crash
  return `${p.firstName} ${p.lastName.toUpperCase()}`;
}

let me: Person;
// Some random logic that might leave me = null
if (whatever) me = null;
// TS will warn you that you have a potential bug right here,
// because you might pass a null value to a method the doesn't support it
fullname(me);

Having null without static typing has been called the "billion dollars mistake".
Many recent modern languages have been designed with null safety (Rust, Swift, Kotlin, ...).
Some older languages such as C# try to retrofit non-nullable references.
Also: documentation when you call other people's code.

@jods4

because using an uninitialized variable can easily be hiding a bug and "defaulting" to some arbitrary value like 0 is very likely not to fix it.

0 is not an arbitrary value. In Go, which is my primary reference here, the zero value has well defined meaning. And of course if something is well defined, then bugs occur, just as you point out, by someone not being familiar with the documented behaviour. It's just in this situation I would be advocating a different documented behaviour.

because JS will behave differently from TS and this is unexpected

I think by virtue of us commenting on a TypeScript forum, you and I have in some (or many) way(s) found Javascript and its specification to be lacking as a language in which to program at scale. So I find the argument "because that's what we expect from Javascript" to be somewhat lacking. Agreed, this is a departure from current behaviour, but if it's well defined and documented it doesn't matter per se.

because TS can't provide a good default for non-nullable objects

I pick up on this under the heading "Non-primitives". If a struct-like concept is introduced then that does have a well defined zero value. The same would be the case for an array (vs a slice)

because there's no good default for union types

Good point; Go does not have union types hence this does not arise.

If you are trying to save keystrokes

This is not my goal.

The benefit is huge! Guarantee at compile-time...

Sorry, it was a poor choice of words. I see the compile time benefits... and I certainly won't argue against any attempt to improve matters at compile time but at runtime (think interfacing with someone else's library) you have no guarantees that the variable you thought was a non-nullable number will not be null, or even undefined.
Consider the following library that I have written:
export function MyFunc(): number;

If you use my library and compile with --strictNullChecks then, as a user of my library, you are probably expecting that the result of MyFunc() will be a non-nullable number.
But I didn't write my library with --strictNullChecks - so in fact at runtime there are occasions when MyFunc() returns undefined, and sometimes null.
How do you catch this situation?
How do you handle it?
Surely you have to rewrite all library definitions along the following lines:
export function MyFunc(): number | undefined | null;

My unease comes from a compile time assertion that cannot be guaranteed to be true at runtime. The discussion about zero-values was an attempt to initiate a discussion about transpilation process that does help to guarantee true non-nullable values at runtime. I can see now I didn't make that particularly clear.
It's been quite an active discussion so apologies if I've missed something in the proposal/comments that covers this...

0 is not an arbitrary value. In Go, which is my primary reference here, the zero value has well defined meaning.

C# uses the same convention for fields of structs or classes (although you have to explicitly initialize variables).
That doesn't make 0 less arbitrary. It is a value that the language has chosen for you and it does not necessarily mean something for your domain. The language could have set everything to -1 and it would have been just the same.

So I find the argument "because that's what we expect from Javascript" to be somewhat lacking.

Except TS follows JS specs even where they are pretty bad (e.g. ASI). Because one scenario that TS supports is taking your existing JS code as-is and compile it with TS.
So I don't think following the JS standard is a "lacking" argument. In fact, I think you need a compelling reason, not to.
Your suggestion also implies a change of behaviour when turning on or off the strictNullChecks compiler flag. I think that's a big no.
// Without --strictNullChecks
let x: number;
assert(x === undefined);

// With --strictNullChecks
let x: number;
assert(x === 0);

This is not my goal

What is it then? Most languages that I know of require definite assignment of local variables, because it's safer.

but at runtime (think interfacing with someone else's library) you have no guarantees that the variable you thought was a non-nullable number will not be null, or even undefined.

Depends on context.

Here we work on large LOB applications so all our code is checked -> foolproof.
Consuming external 3rd party library should also be foolproof. If API says function x(): number do you code defensively in case it returns a string? We don't and null is now no different from string. If it does return null when it says it doesn't then it's a bug in the library definition (or code) and it should be fixed...
If I wrote a library for others to use I would certainly be more defensive and do some early arguments check and report error if I got a null value where I expected something else.

That doesn't make 0 less arbitrary. It is a value that the language has chosen for you and it does not necessarily mean something for your domain. The language could have set everything to -1 and it would have been just the same.

Ok, I'll accept that. My reference to Go (and other languages that chose 0 as the default value for an int equivalent) was to cite prior art that people may be familiar with; I was seeking to use that prior at as an example. And it is the existence of such prior art that leads me to the "arbitrary" value of 0. I don't see this as a critical point of debate in all of this.

Except TS follows JS specs even where they are pretty bad

Let's agree this is a decision that has been taken by someone.

Because one scenario that TS supports is taking your existing JS code as-is and compile it with TS.

....as is this...

In fact, I think you need a compelling reason, not to.

This is your opinion; this might well also be the opinion (and decision) of the language designers. I'm not seeking to try and changes decisions... rather have a discussion around what I see as the main issues around non-nullable types.

This is not my goal

What is it then?

To make TypeScript:

easier to write
easier to read
easier to maintain

In the case of this PR/discussion, I'm hoping to make the runtime safer.

Most languages that I know of require definite assignment of local variables, because it's safer.

I've cited Go as an example where this isn't the case, because of the existence of the zero value concept. I don't cite it as an example to argue "hence we should do it this way",  rather I do so as an example of prior art: such a decision, like all others, has benefits and drawbacks.

but at runtime (think interfacing with someone else's library) you have no guarantees that the variable you thought was a non-nullable number will not be null, or even undefined.

Depends on context.

Unless I've missed something in the Javascript VM spec, it does not depend on context. There is nothing in the runtime that guarantees this. I'm strictly talking about the runtime here...

Here we work on large LOB applications so all our code is checked -> foolproof.

What do you mean by foolproof?

Consuming external 3rd party library should also be foolproof...

Again, not sure what you mean by foolproof here... At compile-time? Runtime safe?

...If API says function x(): number do you code defensively in case it returns a string?

I think you slightly misconstrued my example. In the pre---strictNullChecks world, would you agree it is valid, according to the compiler, for a function defined as follows to return null or even undefined?
export function MyFunc(): number;

The null and undefined types are both sub-types of number. So now you have to know whether the library was written with --strictNullChecks in mind (not forgetting this could simply be a type definition for a Javascript library).
Do we code defensively in case it returns a string? No.
Does this worry me? Yes, because again at runtime we don't have type information available (for checking) at runtime.
How much of a problem is it in reality? I can't tell you with any degree of accuracy...

... If it does return null when it says it doesn't then it's a bug in the library definition (or code) and it should be fixed

Why is it a bug?

If I wrote a library for others to use I would certainly be more defensive and do some early arguments check and report error if I got a null value where I expected something else.

Why would you perform these checks? Earlier you said:

If API says function x(): number do you code defensively in case it returns a string? We don't and null is now no different from string.

So why check the arguments that your library has been passed?
I would posit that you will do so (and I agree it is sensible to do so) because you don't have these runtime guarantees... and because there is this question of whether the caller is using --strictNullChecks or not.

In the case of this PR/discussion, I'm hoping to make the runtime safer.

I'd argue that it is safer to have an error at compile time than an arbitrary value at runtime (even if the value is well-defined).
I am not speaking of cases where you used the "uninitialized" value on purpose, but cases where you did so by mistake.
If you want to use a variable with 0 default value, just initialize it. Your intent will be clearer for readers of your code.

What do you mean by foolproof?

I mean that the situation where the variable is undefined or null cannot happen at runtime and this property was proven by the compiler.

So now you have to know whether the library was written with  --strictNullChecks  in mind (not forgetting this could simply be a type definition for a Javascript library).

From the PR description, .d.ts are only usable in strictNullChecks mode if they have been marked as such. There will be no ambiguity whether a function can return null or not.

Why is it a bug?

Because when a contract say you don't return null and you do, something is wrong (either the contract or the implementation). I think you would agree that if function x(): number returns a string, there is a bug somewhere?

So why check the arguments that your library has been passed?

Because consumers of my library may not read the doc and not use TypeScript, or not use strictNullChecks... In public APIs it's good practice to error as early as possible, even (especially?) if the usage is invalid.
For internal projects we rely on the compiler to do those checks.

What do you mean by foolproof?

I mean that the situation where the variable is undefined or null cannot happen at runtime and this property was proven by the compiler.

The compiler cannot, to my understanding, guarantee anything about the runtime. For a subset of situations where the only code executed at runtime is that which was compiled by a tsc compiler with --strictNullChecks enabled (or some equivalent checker, Flow?), then, yes, you enjoy certain assurances/comfort (but not guarantees, because the runtime is specified to allow this). But in general (read using external libraries) you don't have these assurances.

From the PR description, .d.ts are only usable in strictNullChecks mode if they have been marked as such.

From re-reading the introduction to this PR, it appears the pragma work is being "considered" and is therefore to my mind still outstanding (and not definite at that). Is there an update on this that I missed?

Because when a contract say you don't return null and you do, something is wrong (either the contract or the implementation). I think you would agree that if function x(): number returns a string, there is a bug somewhere?

We are talking at cross purposes here. In the pre---strictNullChecks world, it is entirely valid for something defined to return a number to return null or undefined. You are talking about a world in which the aforementioned pragma exists - in which case, yes, it would be a 'bug' for a function defined to return number, where the .d.ts is marked as --strictNullChecks, to return undefined or null. Notwithstanding the runtime issues that I consider the main issue.

Because consumers of my library...

Why should a different rule exist for consumers of a library? Arguably they have even less control over the code they are consuming. Unless you are consuming a library that falls into the category above: i.e. all code in, referenced and used by the library is compiled by tsc with --strictNullChecks turned on etc.
I think this comes down to not having runtime guarantees about the values a variable (or property in the case of an object) can take, or at least transpiling runtime checks that help assert such things.

FWIW I strongly oppose any automatic implicit default values. In the worst case I would require that they are explicitly specified by the user for every variable.
The proposal by @myitcv introduces surprising runtime behavior. Its not TypeScript's job to change JavaScript's runtime semantics.

The compiler cannot, to my understanding, guarantee anything about the runtime.

It can for example not accept variable declarations for non-undefined types that don't have an initializer, which would be infinitely better than just assigning some random value implicitly without the programmer knowing it.
Especially not when they want to change from no strict null checks to --strictNullChecks. I would never ever want implicit behavior in that case. I would instead want to review all instances of uninitialized variables on a case by case basis and I want the compiler to point them out to me.
Implicit assignment would mean

the compiler not pointing them out and
implicit bugs.

which is the worst possible outcome.

Ok, I'm going to separate out this point about zero values and the point about runtime guarantees because you make a good point.

The proposal by @myitcv introduces surprising runtime behavior.

It is not surprising if it is well documented. However the end of this reply...

Its not TypeScript's job to change JavaScript's runtime semantics.

We can't change the semantics you're right: we have to work with them. This is exactly my point about not having any runtime guarantees about values.

random value implicitly without the programmer knowing it.

The value is not random... it's well defined. Again, see the end of this reply.

Especially not when they want to change from no strict null checks to --strictNullChecks

@spion I very much take your point. This is a strong argument against introducing zero values. If zero values were well defined from the start of TypeScript then we would be in a very different world. But we are not in that different world. Hence I totally concede, they should not be introduced. Thanks for the discussion @jods4 @spion
So I believe my outstanding questions/concerns relate to runtime assertions about non-null values, and the aforementioned pragma.

For those of you interested, the PR for control flow based type checking is now available: #8010.

Wow.  Basically code contracts built in!!! LOVE YOU GUYS!!!

The following code (with strictNullChecks enabled) raises error
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  alert(key + " = " + value);
}

It is a bug?

@dashaus That looks like a bug. BTW, it only repros with --strictNullChecks and --target es6.


[ci skip] adding user @flying-sheep

Checklist

[x] Used a personal fork of the feedstock to propose changes

@conda-forge/core please merge, @raivivek hasn’t updated this in a while

@flying-sheep if you send a PR fixing the recipe and adding yourself, it will make it easier for the core members to merge it without waiting for the maintainers.

I just did that

I just did that. This is the PR where I add myself.

I'm in automate mode here reading tons of notifications, sorry!

Actually, it only adds you. Can you update it to 1.3, that is what I meant. Otherwise this is the same as the not one.

https://github.com/Techtonique/ahead_python/blob/v0.10.0/setup.py

Sure, but we have 1-week wait time for the maintainer to answer. IF you update the recipe and add yourself, we can speed up the process and merge it right away.

@conda-forge-admin, please rerender

Hi @ocefpaf, why did merging this in not publish a new version?

It did work but Anaconda's CDN seems to be very slow lately. I'm getting tons of:

However, after refreshing a few times I did see version 1.4 there.

OK, thank you!


Unexpected behavior for Partial=True

Noticed that if the JSON is missing a ", it is not parsed correctly. I expect
import pydantic_core

print(
    pydantic_core.from_json(
        '{"name": "jaso',
        allow_partial=True,
    )
)
# > {}
# > Expected {'name': 'jaso'}

print(
    pydantic_core.from_json(
        '{"name": "jaso"}',
        allow_partial=True,
    )
)
# > {'name': 'jaso'}

I swear this worked in a previous version?

The behavior here definitely hasn't changed.
Also this is a duplicate of #1263.


Unable to open cookie file '/home/bitcoin/.bitcoin/.cookie': Permission denied

Describe the bug
.cookie Permision denied, when run fulcrum
in bitcoin debug.log file returns
"ThreadRPCServer incorrect password attempt from <IP_ADDRESS>:45744
ThreadRPCServer incorrect password attempt from <IP_ADDRESS>:42374"
Location in guide
(https://raspibolt.org/guide/bonus/bitcoin/fulcrum.html#run-fulcrum)
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
https://prnt.sc/v2ZfenJ9NxLD
Environment

Raspberry Pi 4
Debian 12
Debian GNU/Linux 12 (bookworm)

Additional context
I have checked and rechecked :|

Looks like the same issue is being discussed here: https://github.com/raspibolt/raspibolt/issues/1347
I reverted to rpcauth method to get Fulcrum working.

i am using rpcauth on bitcoin.conf :| can you share ?

well solved.
just this /data/fulcrum/fulcrum.conf
Bitcoin Core settings
bitcoind = <IP_ADDRESS>:8332
rpccookie = /data/bitcoin/.cookie


Document @AndroidJsonized

Include info about how it determines what type to make the field.

Sorry, I don't follow, which field(s)?

As I understand it, @AndroidJsonized takes a JSON string and then generates appropriate getters/setters. How does it determine what type the getter should return for each JSON property? Should we provide that information, or does it infer this from the data?

It will totally infer everything.
The mapping goes as follows -
There are three primitive JSON scalar types, that map to the following machine types:

number - long or double
string - String
boolean - boolean

and for the aggregate types:

{} (Object) - maps to a whole new type, named after the key
[] (List) - maps to a List where SomeType depends on the type of the first element.

There is no limit to the nesting depth.


chore: remove index.md from docs

No need because its an overview on cdk8s-plus as a whole, not pertaining to a specific version. Will be moved to the website repository in https://github.com/cdk8s-team/cdk8s/pull/1024

💔 All backports failed

Status
Branch
Result

❌
k8s-23/main
Backport failed because of merge conflictsYou might need to backport the following PRs to k8s-23/main: - chore: remove v1.22.0 (#1294)

❌
k8s-24/main
Backport failed because of merge conflictsYou might need to backport the following PRs to k8s-24/main: - chore: remove v1.22.0 (#1294)

Manual backport
To create the backport manually run:
backport --pr 1301

Questions ?
Please refer to the Backport tool documentation

💚 All backports created successfully

Status
Branch
Result

✅
k8s-24/main

Questions ?
Please refer to the Backport tool documentation

💚 All backports created successfully

Status
Branch
Result

✅
k8s-23/main

Questions ?
Please refer to the Backport tool documentation


Fix podspec for coredata support

I had to make the following adjustments to the podspec for this to integrate into my project (the new mantle 2.0 branch)
Basically, the 'GCC_PREPROCESSOR_DEFINITIONS' => "OVERCOAT_SUPPORT_COREDATA=1" doesn't work when cocoapods creates the umbrella header for the swift modules without paying attention to the preprocessor macro to include the header implementation. So i'm left with an incomplete module.
I moved the source files into subdirectories that better align with the subspecs.
I also removed the MTLManagedObjectAdapter.h from the Overcoat.h header as that should be pulled in by the consumers where appropriate (like Mantle.h is). I added MTLManagedObjectAdapter as a dependency for the CoreData subspec, and also updated the versioning requirements to the '~>' syntax which is a better way to specify non-breaking newer versions of a pod are supported.
I am not actively using the social support in Overcoat so I don't think i've fixed that integration.

I'll look into this later.
But one issue about the dependency is that I think it's better to keep both Mantle 1.x and 2.x supported, so this is why I wrote
ss.dependency 'Mantle', '<= 3.0'

instead of (in your PR)
ss.dependency 'Mantle', '~> 2.0'

And this is also why I didn't add MTLManagedObjectAdapter as default dependency.
TL;DR;
Any idea about to support only Mantle 2.x or both 1.x and 2.x?

Oh sure, I didn't realize that you wanted to keep support for both, but that's a noble goal. There must be a way to set it up to work across all configurations and versions but I didn't have time to test all the possible configurations and just needed to get it compiling today :)
I'll try and look into it more when I get a chance


UMS crash on Nokia 8 TA-1012

When I open UMS 1.6.2 (an older versions), it crashes with à message about FUSE kernel ans other mass storage things.
Here is the logcat :
https://drive.google.com/file/d/1gKTae4uDhJsY-byG832e-MPy-8y-N4SN/view?usp=drivesdk
Do you plan to correct the issue, or is my phone just not compatible with UMS ? (I saw a message about flashing kernel, what's that ?)

Hi, sorry for my delayed response.
I'm no longer maintaining this project.

is my phone just not compatible with UMS ?
Probably yes. Your kernel might not be supporting the USB gadget driver I think.
Please contact one of your device developers in forums like XDA and request them for a custom kernel with that driver.

Alright I'll do that, thanks for answering


Limit the trigger of autocomplete window a lil bit?

The new autocomplete feature is awesome!
But would it be possible to limit when it appears a little bit. For example, if I just navigate through my prompt with the arrow keys, it will appear even if I'm just passing through a word, and for certain directions (up/down) it will even hinder further movement.
For example, here I am pressing only arrow keys (mostly only up/down):
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/assets/25933468/6f54806a-27a0-4342-b2b8-de3085382b29
So the movement through the text gets "stuck" in the autocomplete.
Not sure what is best, maybe exclude arrow keys to trigger the initial appearance?

Excluding arrows seems like a good solution, i've made that update! Thanks for the feedback.


Feat/information

Pull Request Test Coverage Report for Build<PHONE_NUMBER>0
Details

85 of 86 (98.84%)  changed or added relevant lines in 7 files are covered.
No unchanged relevant lines lost coverage.
Overall coverage decreased (-0.1%) to 94.309%

Changes Missing Coverage
Covered Lines
Changed/Added Lines
%

baseballhub/src/pages/Notes/Feedback/Feedback.tsx
43
44
97.73%

Totals

Change from base Build<PHONE_NUMBER>7:
-0.1%

Covered Lines:
1833

Relevant Lines:
1921

💛  - Coveralls


Fix icosphere vs. UV sphere import/export

Addresses #281: Webots uses icosphere, but the VRML/X3D format use UV sphere causing mismatches during import and export.
Tasks:

Webots:

[x] add Sphere.ico field defining if the Sphere is a Icosphere or a UV sphere
[x] VRML import: import UV sphere by default
[x] Webots Sphere creation: create icosphere by default

WREN:

[x] WREN: add a new function to create a UV sphere

Export:

[ ] VRML export: export sphere as IndexedFaceSet
[x] X3D export: export ico field and use it in webots.js to create a THREE.IcosahedronGeometry instead of a THREE.SphereGeometry

Documentation

[x] update documentation of Sphere node

We should also check the icosphere texture mapping of Webots vs. THREEjs.

Maximum subdivision value for the icosphere in the code and in the doc doesn't match.
I think it is better to change the code and limit the maximum number of faces to 20480, i.e. subdivision 5 and not 6 (81920 faces).

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/551/consoleText

Texture mapping of icosphere in Webots doesn't match the texture mapping of the icosahedron in THREEjs, where it is about the same as for the UV sphere.
In Webots icosphere the texture is stretched (icosphere left and UV sphere right):

We can keep the current texture mapping and use a custom texture mapping for THREEjs in webots.js or change the texture mapping in Webots.

I would change the texture mapping in Webots to make it more standard (similar to the one of THREEjs)

The VRML or X3D specs is ambiguous relatively to the choice between linear or radial texture mapping:

When a texture is applied to a sphere, the texture covers the entire surface ...

http://graphcomp.com/info/specs/sgi/vrml/spec/part1/nodesRef.html#Sphere
http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/geometry3D.html#f-Spherenode

As you propose, radial mapping seems more logical.

Note VRML/X3D use UV spheres and not icospheres.
I checked with different VRML viewers and the new Webots UV sphere matches what is displayed in the other viewers (including THREEjs).
For icosphere there is no VRML/X3D reference to follow.

For icosphere there is no VRML/X3D reference to follow.

This is why should probably follow the implementation of THREEjs for icosphere texture mapping.

Yes, I agree.
It was just to specify that icospheres don't exist in VRML/X3D.

tessellation (ico vs uv) and texture mapping are not related: you can do a linear or radial mapping both on ico or uv spheres (but there will be issues on joints in some cases, influencing the choice). VRML or X3D does specifies the mapping, but does not specifies the tessellation. We are free to choose both.

All the VRML/X3D viewer I found use the UV tessellation and mapping.
So even if you could be theoretically free to choose what we want, this is not possible in practice if we want to be compatible with other software.

I agree :-)

To me, it is important that when we switch the "ico" field of a Sphere from TRUE to FALSE, the texture mapping on the sphere remains unchanged and hence the sphere remains visually very similar.

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/569/consoleText

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/572/consoleText

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/580/consoleText

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/581/consoleText

test me

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/582/consoleText

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

:+1:

:eyes: By the way, why did you set the default value of Sphere.ico to FALSE?

By the way, why did you set the default value of Sphere.ico to FALSE?

Because we want to create a UV sphere when reading a VRML file.

Because we want to create a UV sphere when reading a VRML file.

That breaks badly backward compatibility. Couldn't we instead of that, set the default value to TRUE and change it to FALSE when importing VRML?

The backward compatibility it is not broken.
For spheres stored in files older than R2019b the ico field is automatically set to TRUE.

I am sorry, but I believe that setting the default value of ico to TRUE is better if we want to encourage users to use icosahedra instead of UV spheres.

In practice nothing changes for users in setting different default values:

if they create a Sphere from Webots then it will by default an icosphere
if they load an old Webots file then the world will use icosphere

On the other hand this implementation is more consistent with all the other nodes, where the default values in <Node>.wrl defines the VRML specification.
But I will check if there is a simple way to change the values in case of VRML files.
Also note that the major change that breaks the backwards compatibility is not the tessellation but different texture mapping used for icospheres so that UV and ICO sphere texture mapping is as similar as possible.

test me

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

Build Failed :confused:
https://cyberbotics2.cyberbotics.com:8443/job/Webots/589/consoleText

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

test me

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

:+1:
@omichel: I changed the default values as you requested.
Just note that now the following exact same node definition will produce different results if stored in a VRML or Webots file
Sphere {
  radius 0.1
}

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

:-1:
Some textured spheres have to be adapted:

SoccerBall
..

For the SoccerBall, it can be fixed by changing the texture (the one in the picture is just a test one) and increasing the subdivision value.
Otherwise if we want to keep the number of faces low, we should define it as IndexedFaceSet.
Here is the a icosphere with  subdivision 3.
Further reducing the subdivision will result in more curved lines on the top/bottom area (left ball view)

That looks good to me. Changing the texture is the way to go (if we can find a good one).

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

:+1:

Is it normal to have the soccer ball look like this?

It looks very bad comparing to the RobocupSoccerBall:

No, the first SoccerBall screenshot is the one with old texture. I will check if I missed to update some textures.

I checked and I get the correct SoccerBall when inserting it from the Add Node dialog.

Sorry, my fault, I was not up-to-date with your branch. Recompiling now...

OK, it looks very good to me indeed. Sorry for the confusion.
Maybe we should simply update the SoccerBall proto icon so that it better resembles the new one.

Yes, I will update the icon.

test me

test me

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.

:+1:

Build Passed :ok_hand:
You can safely merge 'fix-icosphere' into 'develop'.


Add documentation for IBM models in nltk.align

No changes to code logic
Add module and method docstrings
Add intermediate variables and inline comments where the computation steps are not clear
Remove redundant comments
Clearer names for methods and variables
Whitespace formatting

Beautiful work on the documentation. I'm going to take your word about no changes to code logic.

Thanks! I used an IDE to do the renaming and double-checked the changes. Plus all the doctests still passed, so I am fairly certain there are no logic changes. The bigger changes will come in upcoming pull requests.


Better default settings for initial install.

In particular:

AMT callbacks always use HTTPS, since AMT now refuses to load any page without SSL in its iFrame.
The default install assumes that the user doesn't have a publicly accessible IP (for local testing).

Test PASSed.
Refer to this link for build results (access rights to CI server needed):
https://amplab.cs.berkeley.edu/jenkins/job/ampcrowd-prb/3/
Test PASSed.


Allow option to send chunking specific params as custom header params

Type of issue

[ ] Bug report
[x] Feature request
[ ] Support request

Uploader type

[x] Traditional
[ ] S3
[ ] Azure

Feature Request
Feature request details
{why is this feature important, not just for you, but for many others?}
For request of traditional uploads, there is an option to set params to be sent within the body (see https://docs.fineuploader.com/branch/master/api/options.html#request.paramsInBody). For an internal project I need the possibility to include the params for chunking requests as custom headers instead, in order to avoid numerous pre-flight requests for cors.
For this purpose I require to configure the options for params in a different way, for example by replacing the option request.paramsInBody with request.paramsMode and a new option -> header | body | url. Of course this approach would cause a breaking change in the core options API, so I am open for another solution.
Optionally for request.header there should be an option to set a prefix for header params (i.e. 'x-upload-'). This could be also set as 'request.headerParamPrefix`.

Custome headers will not help you to avoid preflight requests. And with that I’m going to close this issue since that is the only obvious motivation for this proposal.

This should be covered by #1917.


Prototype a Menu Scene

I suppose this works, but there has to be a cleaner way...
Roadblocks

Abstract Scene?
Where should the scene state machine exist?
How do we manipulate the state?
Should we make a game.h file (so we can add a public GameSetState(SceneState state))?

What if we only had one scene... :thinking:

This is probably a good idea, but it just makes sense (at least in the interest of time) to put everything in Scene. Yeah it's going to get messy, but so is implementing the gameplay preview in a new scene...


Drawer goBack action always re-render

When i goBack action from drawer child, Parent screen alway re-render.
Screen A(Parent) --> Screen B(Child) --> goBack() (this is alway re-render Screen A).
I want to disable re-render when back action from Screen B --> Screen A(Parent)
How can solve this problem?
Thanks!

Hi, please follow the issue template when submitting an issue. It's there to help people help you. Thanks!


Login

Whats the default user/password?? You must add that in documentation. 👍
Also while navigating to Users Master data "DataTables warning: table id=dataTableBuilder - Ajax error." error happening.

Whats the default user/password?? You must add that in documentation. 👍
Also while navigating to Users Master data "DataTables warning: table id=dataTableBuilder - Ajax error." error happening.

You can find the default user and password in the user seeder file here: UsersSeeder.php

Also while navigating to Users Master data "DataTables warning: table id=dataTableBuilder - Ajax error." error happening.


Login Issues

Hii
I don't have 2FA enabled, no . alerts when I login to the website however when I try to push a image I get this:
instapy 0.0.6  |  python 2.7.13
Traceback (most recent call last):
File "/usr/local/bin/instapy", line 11, in
sys.exit(main())
File "/usr/local/lib/python2.7/dist-packages/instapy_cli/main.py", line 48, in main
with client(options.username, password) as cli:
File "/usr/local/lib/python2.7/dist-packages/instapy_cli/cli.py", line 9, in init
self._session.login(username, password)
File "/usr/local/lib/python2.7/dist-packages/instapy_cli/api/session.py", line 66, in login
raise IOError(resp_json.get('message'))
IOError: Sorry, there was a problem with your request.
Am I missing something?

How old is your Instagram account? It took about a week for my new account to start working properly.

@kippi6171 please, re-open this issue with a comment if you run on the same problem.
I'm sure it's the problem @Glarity stated.
🥂


[Backport 1.0] Remove distribution from main response in compatibility mode

This Change removes version.distribution when the version.number is
overridden with the cluster setting compatibility.override_main_response_version.
Signed-off-by: Marc Handalian<EMAIL_ADDRESS>Description
[Describe what this change achieves]
Issues Resolved
[List any issues this PR will resolve]
Check List

[ ] New functionality includes testing.

[ ] All tests pass

[ ] New functionality has been documented.

[ ] New functionality has javadoc added

[ ] Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Well, seems the same checks including "start gradle check" are also required on 1.0 branch now. 😆 They were not at 2pm afternoon when PR # 909 merged.

was this merged to 1.x?

Doesn't look like it. We need to open backport PRs to 1.x then cherry-pick to 1.0.


in_array strict mode

Hi guys,
while testing with PHPUnit in my project I got the following error
Fatal error: Nesting level too deep - recursive dependency? in vendor/spatie/laravel-navigation/src/Navigation.php on line 61
As explained here: Stackoverflow
It would appear that by default in_array does non-strict comparison (equivalent to an == operation) when testing the haystack for the needle. This means that it checks that all the properties are equal, which means it starts traversing the object graph, and that can get you into trouble if you have circular references in that graph.
Solution
This PR activates the in_array strict mode in the file navigation.php on line 61 and with that the error does no longer pop-up.
Environment where error appears
composer show spatie/laravel-navigation
versions : * 1.1.0
PHPUnit 9.5.25
Laravel Version ....................................................................................................... 9.32.0
PHP Version ........................................................................................................... 8.1.10
Composer Version ....................................................................................................... 2.4.2
Environment ............................................................................................................ local
Debug Mode ........................................................................................................... ENABLED

Thanks!