Type Notation warns within editor, albeit not at Runtime

local M: Model = game:GetService('Workspace').Model;
M.Scale = 2.0; -- valid property of all Model instances.

I always liked type-notating my variables, as I did in other languages. Some time ago, though, I started facing this error: type-notating a Model to ‘Model’ wouldn’t work - whenever managing it’s properties or running built-in methods, it’ll say that ‘Key ‘property’ was not found in class ‘Model’’ or ‘‘Method’ is not a valid member of class ‘Model’’.

Not only does this happen with ‘Model’ type, but with every single one else. Type-notating to ‘any’, though, has never given any errors. Even then, it has no meaning to type-notate if 90% of these are 'any’s.

Sorry if this isn’t the right category. It wasn’t that clear to me which one to ask in.
Thanks in advance; any help is appreciated.

I would imagine that this would be because you need to use :SetScale(), writing directly to Scale produces an error. Are you having an issue with other properties of Model?

No error for me in strict mode

image

The warnings produced don’t error at runtime and that’s intentional for the type checking they’ve added. If you’re trying to stop people from sending over invalid data types I would recommend using assert

1 Like

The error still occurs with any other property, even the most common one. Such as ‘Position’ for 'Instance’s. Another example could be the following:

local g: Instance = game; -- print(typeof(game)); outputs 'Instance', therefore this'd be correct.
local GS: (Instance, string) -> (any) = game.GetService; -- Key 'GetService' not found in class 'Instance'. This doesn't happen when type-notating 'g' to 'any'.

By default, my scripts are set to nonstrict. I’ll try with strict mode later to see if that solves the problem.

There is no Position property in an instance: Instance | Documentation - Roblox Creator Hub

You’d be talking about classes such as BaseParts, which inherit the Instance class but then add the positional property. (Forgive my terminology) Unless you mean a Model which has a WorldPivot?

The snippet you sent me isn’t erroring for me, could you send a screenshot of your code? Or a file.

The example with ‘Instance’ was indeed wrong, yes. My bad.
And also, now the code retrieving game and the :GetService() method seems to work. Still, this is an example of what I am referring to:

image

Edit: errors again.
image

I assume that the object you search for in the Players object inside of ReplicatedStorage is made on runtime so this is why the code editor does not see it. This is merely a warning. The editor does not know your intention to add a Settings instance inside which is why it is erroring. I think this will silence if you use nonstrict or findfirstchild

If you send your raw code instead of the screenshot I can try it

local ed = Enum.EasingDirection;
local es = Enum.EasingStyle;


local g: any = game;
local GS: any = g.GetService;


local P: Players = GS(g, 'Players');
local TS: TweenService = GS(g, 'TweenService');
local RSS: ReplicatedStorage = GS(g, 'ReplicatedStorage');

local Fetch = require(RSS:WaitForChild('Fetcher', 30.0));
local MouseInteraction, PlaySound =  Fetch:Event({ ':MouseInteraction()', ':PlaySound()' });
local Debounce, Database, Find, PopUp, Check = Fetch:Script({ 'Debouncer', 'DatabaseManager', 'Recursiver', 'PopUpManager', 'Checker' });


local TI1 = TweenInfo.new(0.5, es.Circular, ed.Out);
local TI2 = TweenInfo.new(0.5, es.Circular, ed.Out);
local TI3 = TweenInfo.new(0.50, es.Circular, ed.Out);

-- local TI4 = TweenInfo.new(5.0, es.Quad, ed.Out);
-- local TI5 = TweenInfo.new(4.0, es.Quad, ed.Out);
local TI6 = TweenInfo.new(0.8, es.Quad, ed.Out);

local TI7 = TweenInfo.new(1.5, es.Quint, ed.InOut);

local TweenSettings1 = { Position = UDim2.new(-0.150, 0, -0.3640, 0) };
local TweenSettings2 = { Position = UDim2.new(0.5920, 0, -0.3640, 0) };

local TweenSettings3 = { Size = UDim2.new(0.30, 0, 0.05, 0) }
local TweenSettings4 = { Position = UDim2.new(0.50, 0,  0.05, 0) }
local TweenSettings5 = { Size = UDim2.new(0.6, 0, 0.6, 0) }
local TweenSettings6 = { Position = UDim2.new(0.5, 0,  0.5, 0) };

local TweenSettings7 = { Position = UDim2.new(1.31, 0, 0.50, 0) };
local TweenSettings8 = { Position = UDim2.new(1.16, 0, 0.05, 0) };


local OriginalSizeY;
local TransparencyTable = { };
local FadeTweens = { }; 
local PropertyMap = {
        [' O'] = 'Transparency',
        [' I'] = 'ImageTransparency',
        [' T'] = 'TextTransparency',
        [' TS'] = 'TextStrokeTransparency',
        [' BG'] = 'BackgroundTransparency',
        [' SB'] = 'ScrollBarImageTransparency',
};



local function Play(Player: Player, Sound: string)
        PlaySound:FireClient(Player, Sound);
end

local function SizeAnimation(Button: any, Amplification: number)
        local SizeX = Button.Parent.Size.X.Scale;
        local SizeY = OriginalSizeY or Button.Parent.Size.Y.Scale;
        OriginalSizeY = SizeY;

        Button.Parent:TweenSize(UDim2.new(SizeX, 0, SizeY * Amplification, 0), ed.InOut, es.Quint, 0.2, false);
end

function AddFadeTween(Element: any, Key: string, IsMinimized: boolean, Type: string)
        local Settings = { };
        local DefaultValue = 1.0;

        if IsMinimized then
                DefaultValue = TransparencyTable[Key] or 1.0;
        end

        local Property = PropertyMap[Type];

        if Property then
                Settings[Property] = DefaultValue;

                table.insert(FadeTweens, TS:Create(Element, TI6, Settings));
        end
end



function Animate(LP: Player, CallType: number, Button: any, PopUpName: string, EventName: string, GFX: boolean, Method: (any?) -> any?)
        local PlayerPopUp, Shader, _, _ = PopUp:Get(LP, PopUpName);
        local Frame = Button.Parent.Parent;

        local CloseFrame, MinimizeFrame, CloseButton, MinimizeButton, Minimized, Title = Check:ForInstance({ 'Close', 'Minimize', 'CloseButton', 'MinimizeButton', 'Minimized', 'Title' }, Frame, true, 'Unpacked');
        local Separator, UIGradient, UICorner, UIStroke = Check:ForInstance({ 'Separator', 'UIGradient', 'UICorner', 'UIStroke' }, Frame, false, 'Unpacked');
        local IsMinimized = Minimized.Value;

        local function ChangeState(SizeSettings: { }, PositionSettings: { }, SizeX: number, SizeY: number, Text: string)
                Debounce('PopUp', 2.0);

                local SizeTween = TS:Create(Frame, TI6, SizeSettings);
                local PositionTween = TS:Create(Frame, TI6, PositionSettings);
                local SeparatorTween = TS:Create(Separator, TI6, { Size = UDim2.new(SizeX, 0, 0, 0) });
                
                local AdditionalTweens = {
                        TS:Create(CloseFrame, TI6, { Size = UDim2.new(0.1, 0, SizeY, 0) }),
                        TS:Create(MinimizeFrame, TI6, { Size = UDim2.new(0.1, 0, SizeY, 0) }),
                        TS:Create(Title, TI6, { Size = UDim2.new(0.76, 0, SizeY, 0) }),
                        TS:Create(UICorner, TI6, { CornerRadius = UDim.new(SizeY, 0) }),
                };

                OriginalSizeY = SizeY;

                for _, Element in ipairs (Frame:GetDescendants()) do
                        local Parent = Element.Parent or '';
                        
                        if (Parent ~= Frame and Parent ~= CloseFrame and Parent ~= MinimizeFrame and Parent ~= Separator) then

                                for Suffix, Property in pairs(PropertyMap) do
                                        local HasProperty, Value = table.unpack(Check:ForProperty({ Element }, Property));

                                        if  HasProperty then
                                                local Key = Element.Name .. Suffix;

                                                AddFadeTween(Element, Key, IsMinimized, Suffix);
                                                TransparencyTable[Key] = Value;
                                        end
                                end
                        end
                end

                if IsMinimized then
                        PositionTween:Play();
                        PositionTween.Completed:Wait();
                        
                        SizeTween:Play();
                        
                        task.wait(TI6.Time / 8);
                        
                        Separator.Visible = true;
                        SeparatorTween:Play();

                        for i, Tween in ipairs(AdditionalTweens) do
                                Tween:Play();

                                if #AdditionalTweens == i then
                                        Tween.Completed:Wait();
                                end
                        end
                        
                        MinimizeButton.Text = Text;
                        
                        for i, Tween in ipairs(FadeTweens) do
                                Tween:Play();
                        end
                else
                        SeparatorTween:Play();
                        
                        for i, Tween in ipairs(FadeTweens) do
                                Tween:Play();

                                if #FadeTweens == i then
                                        Tween.Completed:Wait();
                                end
                        end

                        SizeTween:Play();

                        for i, Tween in ipairs(AdditionalTweens) do
                                Tween:Play();

                                if #AdditionalTweens == i then
                                        Tween.Completed:Wait();
                                end
                        end
                        
                        MinimizeButton.Text = Text;
                        
                        SizeTween.Completed:Wait();
                        PositionTween:Play();
                end

                table.clear(FadeTweens);
                table.clear(AdditionalTweens);

                task.wait(TI6.Time / 4);

                if not IsMinimized then
                        Separator.Visible = false;
                end

                Minimized.Value = not Minimized.Value;

                PopUp:DisableShader(Shader, GFX);        
        end

        local function Close()
                Debounce('PopUp', 3.0);

                local Tween;
                if IsMinimized then
                        Tween = TS:Create(Frame, TI7, TweenSettings8);                         
                else
                        Tween = TS:Create(Frame, TI7, TweenSettings7);
                end

                Tween:Play();
                task.wait(1.0);
                PopUp:DisableShader(Shader, GFX);

                task.spawn(function()
                        task.wait(1.5)

                        if IsMinimized then
                                ChangeState(TweenSettings5, TweenSettings6, 0.95, 0.1, '-');
                        end

                        Frame.Visible = false;
                end);
        end

        local function TweenSlider()
                Debounce('SettingChange', 0.5);

                local Circle = Button.Parent.Circle;
                local SettingName = Circle.Parent.Parent.Name;

                local Setting = Fetch:Setting(LP, 'Settings', { SettingName });
                local SettingObject = RSS:WaitForChild('Players', 30.0):WaitForChild(tostring(LP.UserId), 30.0).Settings.Audiovisual:WaitForChild(SettingName, 30.0);
                local Enabled = SettingObject.Value;

                if GFX then
                        local Tween1 = TS:Create(Circle, TI1, TweenSettings1);
                        local Tween2 = TS:Create(Circle, TI2, TweenSettings2);

                        local function AnimateColor(ColorN: Color3)
                                local TweenSettings3 = {
                                        BackgroundColor3 = ColorN
                                };                                
                                local Tween3 = TS:Create(Circle, TI3, TweenSettings3);

                                Tween3:Play();
                        end

                        if Enabled then
                                AnimateColor(Color3.fromRGB(188.0, 137.0, 225.0));
                                Tween1:Play()
                        else 
                                AnimateColor(Color3.fromRGB(119.0, 225.0, 207.0));
                                Tween2:Play()
                        end
                else
                        if Enabled then
                                Circle.Position = UDim2.new(-0.150, 0.0, -0.3640, 0.0);
                                Circle.BackgroundColor3 = Color3.fromRGB(188.0, 137.0, 225.0);
                        else
                                Circle.Position = UDim2.new(0.5920, 0.0, -0.3640, 0.0);
                                Circle.BackgroundColor3 = Color3.fromRGB(119.0, 225.0, 207.0);
                        end
                end

                SettingObject.Value = not SettingObject.Value;        
        end

        if CallType == 0.0 then
                SizeAnimation(Button, 1.050);
        elseif CallType == 2.0 then
                SizeAnimation(Button, 0.950);
        elseif CallType >= 1.0 then
                SizeAnimation(Button, 1.0);

                if CallType == 1.5 then
                        if EventName == 'Close' then
                                Close();
                        elseif EventName == 'Minimize' then
                                if IsMinimized then
                                        ChangeState(TweenSettings5, TweenSettings6, 0.95, 0.1, '-');
                                else
                                        ChangeState(TweenSettings3, TweenSettings4, 0.0, 1.0, '+');
                                end
                        elseif EventName == 'Slide' then
                                TweenSlider();
                        else
                                MouseInteraction:FireServer(EventName);  
                        end
                end
        end
end



return Animate;

Change TweenSlider function to this

local function TweenSlider()
		Debounce('SettingChange', 0.5);

		local Circle = Button.Parent.Circle;
		local SettingName = Circle.Parent.Parent.Name;

		local Setting = Fetch:Setting(LP, 'Settings', { SettingName });
		local PlayersObject = RSS:WaitForChild("Players", 30.0)
		local MyPlayer = PlayersObject:WaitForChild(tostring(LP.UserId), 30)
		local SettingObject = MyPlayer.Settings.Audiovisual:WaitForChild(SettingName, 30.0);
		
		local Enabled = SettingObject.Value;

		if GFX then
			local Tween1 = TS:Create(Circle, TI1, TweenSettings1);
			local Tween2 = TS:Create(Circle, TI2, TweenSettings2);

			local function AnimateColor(ColorN: Color3)
				local TweenSettings3 = {
					BackgroundColor3 = ColorN
				};                                
				local Tween3 = TS:Create(Circle, TI3, TweenSettings3);

				Tween3:Play();
			end

			if Enabled then
				AnimateColor(Color3.fromRGB(188.0, 137.0, 225.0));
				Tween1:Play()
			else 
				AnimateColor(Color3.fromRGB(119.0, 225.0, 207.0));
				Tween2:Play()
			end
		else
			if Enabled then
				Circle.Position = UDim2.new(-0.150, 0.0, -0.3640, 0.0);
				Circle.BackgroundColor3 = Color3.fromRGB(188.0, 137.0, 225.0);
			else
				Circle.Position = UDim2.new(0.5920, 0.0, -0.3640, 0.0);
				Circle.BackgroundColor3 = Color3.fromRGB(119.0, 225.0, 207.0);
			end
		end

		SettingObject.Value = not SettingObject.Value;        
	end

I’m not entirely sure why there was an error on yours compared to breaking it down like what I did in mine but it’s most likely just a type check mistake. Remember that these aren’t errors but merely warnings so will work on runtime but just show as an error while editing.

1 Like

What about the other error?

local g: Instance = game;
local GS: (Instance, string) -> (any) = g.GetService;

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.