How to update the function

function DialogModule:typeText(label, text, callback)
	label.Text = ""
	for i = 1, #text do
		label.Text = string.sub(text, 1, i)
		wait(0.01)
	end
	if callback then callback() end
end

What’s the problem? You’ve just sent some code without any context whatsoever.

when I use this function it writes text, but when I use it again the text does not change and gets confused

Can you show me the code that uses the function?

Of course, unfortunately there was no answer to the last post

local DialogModule = {}
DialogModule.__index = DialogModule

local NPCDialogs = {
	NPC1 = {
		name = "Mr.Li",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"Welcome to our village. We need your help."
		},
		quest = "FindTheTreasure",
		gui = nil
	},
	NPC2 = {
		name = "Sun.Chan",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"This is Alchemy Gui. You can Create a Potion."
		},
		quest = nil,
		gui = nil
	},
	NPC3 = {
		name = "Change Rasa",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"This is Rasa Gui. You can Change your Rasa."
		},
		quest = nil,
		gui = "ChangeRasa"
	},
	NPC4 = {
		name = "Let.Kin",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"PLS HELP ME"
		},
		quest = "Collect20Coins",
		gui = nil
	},
}

function DialogModule.new(player: Player, npcName: string)
	local self = setmetatable({}, DialogModule)
	
	self.npcName = npcName
	self.player = player
	self.currentMessageIndex = 1
	self.dialogData = NPCDialogs[npcName]
	self.isQuest = self.dialogData and self.dialogData.quest ~= nil
	self.hasGUI = self.dialogData and self.dialogData.gui ~= nil
	self.questModule = require(Modules.Quests).new(player)

	return self
end

function DialogModule:typeText(label, text, callback)
	label.Text = ""
	for i = 1, #text do
		label.Text = string.sub(text, 1, i)
		wait(0.01)
	end
	if callback then callback() end
end

function DialogModule:formatMessage(message)
	message = message:gsub("{PlayerName}", self.player.Name)
	message = message:gsub("{NPCName}", self.dialogData.name)
	return message
end

function DialogModule:resetDialog(DialogGui)
	self.currentMessageIndex = 1
	DialogGui.Visible = false
	DialogGui.Parent.Blur.Visible = false
	DialogGui.Parent.Attack.Visible = true
	DialogGui.Parent.Rasa.Visible = true
end

function DialogModule:startDialog(DialogGui)
	CloseAllFrame()
	self.DialogGui = DialogGui

	local DialogTitle = DialogGui.Title.Title
	local DialogText = DialogGui.Text.Title
	local DialogButtons = DialogGui.Buttons

	local nextButton = DialogButtons.Next
	local closeButton = DialogButtons.Close
	local acceptButton = DialogButtons.Accept
	local declineButton = DialogButtons.Decline

	DialogTitle.Text = self.dialogData.name

	nextButton.Visible = true
	closeButton.Visible = true
	acceptButton.Visible = false
	declineButton.Visible = false

	DialogGui.Parent.Blur.Visible = true
	DialogGui.Parent.Attack.Visible = false
	DialogGui.Parent.Rasa.Visible = false

	DialogGui.Visible = true

	local formattedMessage = self:formatMessage(self.dialogData.messages[self.currentMessageIndex])
	self:typeText(DialogText, formattedMessage)

	local function onNextButtonClick()
		self.currentMessageIndex += 1
		if self.currentMessageIndex <= #self.dialogData.messages then
			local nextFormattedMessage = self:formatMessage(self.dialogData.messages[self.currentMessageIndex])
			self:typeText(DialogText, nextFormattedMessage)
		else
			if self.isQuest then
				nextButton.Visible = false
				closeButton.Visible = false
				acceptButton.Visible = true
				declineButton.Visible = true
				self:completeQuest(DialogText)
			elseif self.hasGUI then
				nextButton.Visible = false
				closeButton.Visible = true
				acceptButton.Visible = false
				declineButton.Visible = false
				self:openCustomGUI()
			else
				self:resetDialog(DialogGui)
			end
		end
	end

	nextButton.Button.MouseButton1Click:Connect(onNextButtonClick)

	closeButton.Button.MouseButton1Click:Connect(function()
		self:resetDialog(DialogGui)
	end)

	declineButton.Button.MouseButton1Click:Connect(function()
		self:resetDialog(DialogGui)
	end)

	acceptButton.Button.MouseButton1Click:Connect(function()
		if self.isQuest then
			self.questModule:startQuest(self.dialogData.quest)
		end
		self:resetDialog(DialogGui)
	end)
end

Are you sure that the later calls of self:typeText() are being made?

local function onNextButtonClick()
		self.currentMessageIndex += 1
		if self.currentMessageIndex <= #self.dialogData.messages then
			local nextFormattedMessage = self:formatMessage(self.dialogData.messages[self.currentMessageIndex])
			print(nextFormattedMessage)
			self:typeText(DialogText, nextFormattedMessage)
		else
			...

Try that, and see if it prints anything.

I probably should have given you the full code

local Services = require(game.ReplicatedStorage.Utils.Services).new():GetServices()
local Variables = require(game.ReplicatedStorage.Utils.Variables).new():GetVariables()

local Player = Variables.Player
local PlayerGui = Player:WaitForChild("PlayerGui")

local Modules = Variables.Modules

local Main = PlayerGui:WaitForChild("Main")
local Frames = Main.Frames

local Blur = Main:WaitForChild("Blur")
local Camera = workspace.CurrentCamera

local function CloseAllFrame()
	for _, frame in pairs(Frames:GetChildren()) do
		if frame:IsA("Frame") then
			frame.Visible = false
		end
	end
	Services.TweenService:Create(Camera, TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {FieldOfView = 70}):Play()
	Blur.Visible = true
end

local DialogModule = {}
DialogModule.__index = DialogModule

local NPCDialogs = {
	NPC1 = {
		name = "Mr.Li",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"Welcome to our village. We need your help."
		},
		quest = "FindTheTreasure",
		gui = nil
	},
	NPC2 = {
		name = "Sun.Chan",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"This is Alchemy Gui. You can Create a Potion."
		},
		quest = nil,
		gui = nil
	},
	NPC3 = {
		name = "Change Rasa",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"This is Rasa Gui. You can Change your Rasa."
		},
		quest = nil,
		gui = "ChangeRasa"
	},
	NPC4 = {
		name = "Let.Kin",
		messages = {
			"Hello, {PlayerName}! I am {NPCName}",
			"PLS HELP ME"
		},
		quest = "Collect20Coins",
		gui = nil
	},
}

function DialogModule.new(player: Player, npcName: string)
	local self = setmetatable({}, DialogModule)
	
	self.npcName = npcName
	self.player = player
	self.currentMessageIndex = 1
	self.dialogData = NPCDialogs[npcName]
	self.isQuest = self.dialogData and self.dialogData.quest ~= nil
	self.hasGUI = self.dialogData and self.dialogData.gui ~= nil
	self.questModule = require(Modules.Quests).new(player)

	return self
end

function DialogModule:typeText(label, text, callback)
	label.Text = ""
	for i = 1, #text do
		label.Text = string.sub(text, 1, i)
		wait(0.01)
	end
	if callback then callback() end
end

function DialogModule:formatMessage(message)
	message = message:gsub("{PlayerName}", self.player.Name)
	message = message:gsub("{NPCName}", self.dialogData.name)
	return message
end

function DialogModule:resetDialog(DialogGui)
	self.currentMessageIndex = 1
	DialogGui.Visible = false
	DialogGui.Parent.Blur.Visible = false
	DialogGui.Parent.Attack.Visible = true
	DialogGui.Parent.Rasa.Visible = true
end

function DialogModule:startDialog(DialogGui)
	CloseAllFrame()
	self.DialogGui = DialogGui

	local DialogTitle = DialogGui.Title.Title
	local DialogText = DialogGui.Text.Title
	local DialogButtons = DialogGui.Buttons

	local nextButton = DialogButtons.Next
	local closeButton = DialogButtons.Close
	local acceptButton = DialogButtons.Accept
	local declineButton = DialogButtons.Decline

	DialogTitle.Text = self.dialogData.name

	nextButton.Visible = true
	closeButton.Visible = true
	acceptButton.Visible = false
	declineButton.Visible = false

	DialogGui.Parent.Blur.Visible = true
	DialogGui.Parent.Attack.Visible = false
	DialogGui.Parent.Rasa.Visible = false

	DialogGui.Visible = true

	local formattedMessage = self:formatMessage(self.dialogData.messages[self.currentMessageIndex])
	self:typeText(DialogText, formattedMessage)

	local function onNextButtonClick()
		self.currentMessageIndex += 1
		if self.currentMessageIndex <= #self.dialogData.messages then
			local nextFormattedMessage = self:formatMessage(self.dialogData.messages[self.currentMessageIndex])
			print(nextFormattedMessage)
			self:typeText(DialogText, nextFormattedMessage)
		else
			if self.isQuest then
				nextButton.Visible = false
				closeButton.Visible = false
				acceptButton.Visible = true
				declineButton.Visible = true
				self:completeQuest(DialogText)
			elseif self.hasGUI then
				nextButton.Visible = false
				closeButton.Visible = true
				acceptButton.Visible = false
				declineButton.Visible = false
				self:openCustomGUI()
			else
				self:resetDialog(DialogGui)
			end
		end
	end

	nextButton.Button.MouseButton1Click:Connect(onNextButtonClick)

	closeButton.Button.MouseButton1Click:Connect(function()
		self:resetDialog(DialogGui)
	end)

	declineButton.Button.MouseButton1Click:Connect(function()
		self:resetDialog(DialogGui)
	end)

	acceptButton.Button.MouseButton1Click:Connect(function()
		if self.isQuest then
			self.questModule:startQuest(self.dialogData.quest)
		end
		self:resetDialog(DialogGui)
	end)
end

function DialogModule:completeQuest(label)
	if self.isQuest then
		local questInfo = self.questModule:getQuestInfo(self.dialogData.quest)
		if questInfo then
			if self.questModule:isQuestComplete(self.dialogData.quest) then
				self:typeText(label, "Quest already completed!")
				self:setupButtonsForCompletedQuest()
			elseif self.questModule:isQuestStarted(self.dialogData.quest) then
				self:typeText(label, "Quest already claimed!")
				self:setupButtonsForClaimedQuest()
			else
				self:typeText(label, "Quest available: " .. questInfo.title)
				self:setupButtonsForAvailableQuest()
			end
		else
			self:typeText(label, "Quest information not found.")
			self:setupButtonsForCompletedQuest()
		end
	end
end

function DialogModule:setupButtonsForCompletedQuest()
	local DialogButtons = self.DialogGui.Buttons
	DialogButtons.Close.Visible = true
	DialogButtons.Next.Visible = false
	DialogButtons.Accept.Visible = false
	DialogButtons.Decline.Visible = false
end

function DialogModule:setupButtonsForClaimedQuest()
	local DialogButtons = self.DialogGui.Buttons
	DialogButtons.Close.Visible = true
	DialogButtons.Next.Visible = false
	DialogButtons.Accept.Visible = false
	DialogButtons.Decline.Visible = false
end

function DialogModule:setupButtonsForAvailableQuest()
	local DialogButtons = self.DialogGui.Buttons
	DialogButtons.Accept.Visible = true
	DialogButtons.Decline.Visible = true
	DialogButtons.Next.Visible = false
	DialogButtons.Close.Visible = false
end

function DialogModule:openCustomGUI()
	if self.hasGUI then
		local customGUI = Frames[self.dialogData.gui]
		if customGUI then
			CloseAllFrame()
			customGUI.Visible = true
			Services.TweenService:Create(Camera, TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {FieldOfView = 80}):Play()
		end
	end
end

return DialogModule

local function onDialogEvent(npcName: string)
	local dialog = require(Modules.Dialog).new(Player, npcName)
	dialog:startDialog(DialogGui)
end
RemoteEvents.Dialog.OnClientEvent:Connect(onDialogEvent)

the thing is that there are 2 options, option 1 - opening the gui, option 2 - issuing a quest
and when you have completed the opening of the gui, then in the next dialogue with the quest the same gui opens, although this should not happen